Browse code

Merge branch 'ser_core_cvs' of ssh://git.sip-router.org/sip-router

* 'ser_core_cvs' of ssh://git.sip-router.org/sip-router:
tcp: config option to disable active connects
tcp: async mode on by default
tcp: enable runtime changing for most of the cfg vars
tcp: use dynamic config framework, part 2
tcp: use dynamic config framework, part 1
test: updated parse uri test program
sctp: rpc info command
sctp: connection reuse & connection tracking
sctp: empty sctp_handle_assoc_change added
regfree() function call is added to free the memory allocated by regcomp().

Conflicts:
usr_avp.c - regex free fix from sip-router conflicted with the
one from ser (they were the same)

Andrei Pelinescu-Onciul authored on 05/03/2009 17:43:52
Showing 20 changed files
... ...
@@ -229,12 +229,15 @@ modules:
229 229
                         - t_set_retr(t1, t2) - changes the retransmissions
230 230
                            intervals on the fly, on a per transaction basis.
231 231
 core:
232
+             - most tcp config vars migrated to the dynamic config framework
233
+               (can be changed at runtime, e.g. 
234
+                 sercmd cfg.set_now_int tcp connection_lifetime 180 )
232 235
              - fallback to tcp or other congestion controlled transport 
233 236
                protocol if a forwarded udp sip request is greater then 
234 237
                udp_mtu (config). Default off. See udp_mtu and 
235 238
                udp_mtu_try_proto.
236 239
              - sctp support (one-to-many, work in progress, for now linux
237
-               only with no fallback to one-to-one on full send buffers)
240
+               and freebsd only)
238 241
              - partial cygwin (windows) support revived: core+static modules, 
239 242
                no ipv6, no tcp, no dynamic modules
240 243
              - most of the config variables can now be changed on the fly,
... ...
@@ -253,6 +256,9 @@ core:
253 253
                between the short name and long name in cache as CNAME record
254 254
 
255 255
 new config variables:
256
+  tcp_no_connect = yes/no - disable connects, ser will only accept new 
257
+                     connections, it will never try to open new ones.
258
+                     Default: no, can be changed at runtime.
256 259
   udp_mtu = number - fallback to another protocol (udp_mtu_try_proto must be
257 260
                      set also either globally or per packet) if the constructed
258 261
                      request size is greater then udp_mtu.
... ...
@@ -293,10 +299,10 @@ new config variables:
293 293
      will be cached inside the process calling tcp_send (performance increase
294 294
      for sending over tcp at the cost of slightly slower connection closing and
295 295
      extra FDs kept open)
296
-  tcp_async = yes | no (default no) - if enabled all the tcp  writes that 
296
+  tcp_async = yes | no (default yes) - if enabled all the tcp  writes that 
297 297
      would block / wait for connect to finish, will be queued and attempted
298 298
      latter (see also tcp_conn_wq_max and tcp_wq_max).
299
-  tcp_buf_write = synonim for tcp_async
299
+  tcp_buf_write = obsoleted synonim for tcp_async
300 300
   tcp_conn_wq_max = bytes (default 32 K) - maximum bytes queued for write 
301 301
      allowed per connection. Attempting to queue more bytes would result
302 302
      in an error and in the connection being closed (too slow). If 
... ...
@@ -325,6 +325,7 @@ TCP_CONNECT_TIMEOUT	"tcp_connect_timeout"
325 325
 TCP_CON_LIFETIME	"tcp_connection_lifetime"
326 326
 TCP_POLL_METHOD		"tcp_poll_method"
327 327
 TCP_MAX_CONNECTIONS	"tcp_max_connections"
328
+TCP_NO_CONNECT		"tcp_no_connect"
328 329
 TCP_SOURCE_IPV4		"tcp_source_ipv4"
329 330
 TCP_SOURCE_IPV6		"tcp_source_ipv6"
330 331
 TCP_OPT_FD_CACHE	"tcp_fd_cache"
... ...
@@ -624,6 +625,8 @@ EAT_ABLE	[\ \t\b\r]
624 624
 									return TCP_POLL_METHOD; }
625 625
 <INITIAL>{TCP_MAX_CONNECTIONS}	{ count(); yylval.strval=yytext;
626 626
 									return TCP_MAX_CONNECTIONS; }
627
+<INITIAL>{TCP_NO_CONNECT}		{ count(); yylval.strval=yytext;
628
+									return TCP_NO_CONNECT; }
627 629
 <INITIAL>{TCP_SOURCE_IPV4}		{ count(); yylval.strval=yytext;
628 630
 									return TCP_SOURCE_IPV4; }
629 631
 <INITIAL>{TCP_SOURCE_IPV6}		{ count(); yylval.strval=yytext;
... ...
@@ -389,6 +389,7 @@ static int case_check_default(struct case_stms* stms);
389 389
 %token TCP_CON_LIFETIME
390 390
 %token TCP_POLL_METHOD
391 391
 %token TCP_MAX_CONNECTIONS
392
+%token TCP_NO_CONNECT
392 393
 %token TCP_SOURCE_IPV4
393 394
 %token TCP_SOURCE_IPV6
394 395
 %token TCP_OPT_FD_CACHE
... ...
@@ -814,7 +815,7 @@ assign_stm:
814 814
 	| DISABLE_TCP EQUAL error { yyerror("boolean value expected"); }
815 815
 	| TCP_ACCEPT_ALIASES EQUAL NUMBER {
816 816
 		#ifdef USE_TCP
817
-			tcp_accept_aliases=$3;
817
+			tcp_default_cfg.accept_aliases=$3;
818 818
 		#else
819 819
 			warn("tcp support not compiled in");
820 820
 		#endif
... ...
@@ -830,7 +831,7 @@ assign_stm:
830 830
 	| TCP_CHILDREN EQUAL error { yyerror("number expected"); }
831 831
 	| TCP_CONNECT_TIMEOUT EQUAL intno {
832 832
 		#ifdef USE_TCP
833
-			tcp_connect_timeout=$3;
833
+			tcp_default_cfg.connect_timeout_s=$3;
834 834
 		#else
835 835
 			warn("tcp support not compiled in");
836 836
 		#endif
... ...
@@ -838,7 +839,7 @@ assign_stm:
838 838
 	| TCP_CONNECT_TIMEOUT EQUAL error { yyerror("number expected"); }
839 839
 	| TCP_SEND_TIMEOUT EQUAL intno {
840 840
 		#ifdef USE_TCP
841
-			tcp_send_timeout=$3;
841
+			tcp_default_cfg.send_timeout_s=$3;
842 842
 		#else
843 843
 			warn("tcp support not compiled in");
844 844
 		#endif
... ...
@@ -846,7 +847,7 @@ assign_stm:
846 846
 	| TCP_SEND_TIMEOUT EQUAL error { yyerror("number expected"); }
847 847
 	| TCP_CON_LIFETIME EQUAL intno {
848 848
 		#ifdef USE_TCP
849
-			tcp_con_lifetime=$3;
849
+			tcp_default_cfg.con_lifetime_s=$3;
850 850
 		#else
851 851
 			warn("tcp support not compiled in");
852 852
 		#endif
... ...
@@ -889,6 +890,14 @@ assign_stm:
889 889
 		#endif
890 890
 	}
891 891
 	| TCP_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
892
+	| TCP_NO_CONNECT EQUAL NUMBER {
893
+		#ifdef USE_TCP
894
+			tcp_default_cfg.no_connect=$3;
895
+		#else
896
+			warn("tcp support not compiled in");
897
+		#endif
898
+	}
899
+	| TCP_NO_CONNECT EQUAL error { yyerror("boolean value expected"); }
892 900
 	| TCP_SOURCE_IPV4 EQUAL ipv4 {
893 901
 		#ifdef USE_TCP
894 902
 			if (tcp_set_src_addr($3)<0)
... ...
@@ -915,7 +924,7 @@ assign_stm:
915 915
 	| TCP_SOURCE_IPV6 EQUAL error { yyerror("IPv6 address expected"); }
916 916
 	| TCP_OPT_FD_CACHE EQUAL NUMBER {
917 917
 		#ifdef USE_TCP
918
-			tcp_options.fd_cache=$3;
918
+			tcp_default_cfg.fd_cache=$3;
919 919
 		#else
920 920
 			warn("tcp support not compiled in");
921 921
 		#endif
... ...
@@ -923,7 +932,7 @@ assign_stm:
923 923
 	| TCP_OPT_FD_CACHE EQUAL error { yyerror("boolean value expected"); }
924 924
 	| TCP_OPT_BUF_WRITE EQUAL NUMBER {
925 925
 		#ifdef USE_TCP
926
-			tcp_options.tcp_buf_write=$3;
926
+			tcp_default_cfg.async=$3;
927 927
 		#else
928 928
 			warn("tcp support not compiled in");
929 929
 		#endif
... ...
@@ -931,7 +940,7 @@ assign_stm:
931 931
 	| TCP_OPT_BUF_WRITE EQUAL error { yyerror("boolean value expected"); }
932 932
 	| TCP_OPT_CONN_WQ_MAX EQUAL NUMBER {
933 933
 		#ifdef USE_TCP
934
-			tcp_options.tcpconn_wq_max=$3;
934
+			tcp_default_cfg.tcpconn_wq_max=$3;
935 935
 		#else
936 936
 			warn("tcp support not compiled in");
937 937
 		#endif
... ...
@@ -939,7 +948,7 @@ assign_stm:
939 939
 	| TCP_OPT_CONN_WQ_MAX error { yyerror("boolean value expected"); }
940 940
 	| TCP_OPT_WQ_MAX EQUAL NUMBER {
941 941
 		#ifdef USE_TCP
942
-			tcp_options.tcp_wq_max=$3;
942
+			tcp_default_cfg.tcp_wq_max=$3;
943 943
 		#else
944 944
 			warn("tcp support not compiled in");
945 945
 		#endif
... ...
@@ -947,7 +956,7 @@ assign_stm:
947 947
 	| TCP_OPT_WQ_MAX error { yyerror("boolean value expected"); }
948 948
 	| TCP_OPT_DEFER_ACCEPT EQUAL NUMBER {
949 949
 		#ifdef USE_TCP
950
-			tcp_options.defer_accept=$3;
950
+			tcp_default_cfg.defer_accept=$3;
951 951
 		#else
952 952
 			warn("tcp support not compiled in");
953 953
 		#endif
... ...
@@ -955,7 +964,7 @@ assign_stm:
955 955
 	| TCP_OPT_DEFER_ACCEPT EQUAL error { yyerror("boolean value expected"); }
956 956
 	| TCP_OPT_DELAYED_ACK EQUAL NUMBER {
957 957
 		#ifdef USE_TCP
958
-			tcp_options.delayed_ack=$3;
958
+			tcp_default_cfg.delayed_ack=$3;
959 959
 		#else
960 960
 			warn("tcp support not compiled in");
961 961
 		#endif
... ...
@@ -963,7 +972,7 @@ assign_stm:
963 963
 	| TCP_OPT_DELAYED_ACK EQUAL error { yyerror("boolean value expected"); }
964 964
 	| TCP_OPT_SYNCNT EQUAL NUMBER {
965 965
 		#ifdef USE_TCP
966
-			tcp_options.syncnt=$3;
966
+			tcp_default_cfg.syncnt=$3;
967 967
 		#else
968 968
 			warn("tcp support not compiled in");
969 969
 		#endif
... ...
@@ -971,7 +980,7 @@ assign_stm:
971 971
 	| TCP_OPT_SYNCNT EQUAL error { yyerror("number expected"); }
972 972
 	| TCP_OPT_LINGER2 EQUAL NUMBER {
973 973
 		#ifdef USE_TCP
974
-			tcp_options.linger2=$3;
974
+			tcp_default_cfg.linger2=$3;
975 975
 		#else
976 976
 			warn("tcp support not compiled in");
977 977
 		#endif
... ...
@@ -979,7 +988,7 @@ assign_stm:
979 979
 	| TCP_OPT_LINGER2 EQUAL error { yyerror("number expected"); }
980 980
 	| TCP_OPT_KEEPALIVE EQUAL NUMBER {
981 981
 		#ifdef USE_TCP
982
-			tcp_options.keepalive=$3;
982
+			tcp_default_cfg.keepalive=$3;
983 983
 		#else
984 984
 			warn("tcp support not compiled in");
985 985
 		#endif
... ...
@@ -987,7 +996,7 @@ assign_stm:
987 987
 	| TCP_OPT_KEEPALIVE EQUAL error { yyerror("boolean value expected");}
988 988
 	| TCP_OPT_KEEPIDLE EQUAL NUMBER {
989 989
 		#ifdef USE_TCP
990
-			tcp_options.keepidle=$3;
990
+			tcp_default_cfg.keepidle=$3;
991 991
 		#else
992 992
 			warn("tcp support not compiled in");
993 993
 		#endif
... ...
@@ -995,7 +1004,7 @@ assign_stm:
995 995
 	| TCP_OPT_KEEPIDLE EQUAL error { yyerror("number expected"); }
996 996
 	| TCP_OPT_KEEPINTVL EQUAL NUMBER {
997 997
 		#ifdef USE_TCP
998
-			tcp_options.keepintvl=$3;
998
+			tcp_default_cfg.keepintvl=$3;
999 999
 		#else
1000 1000
 			warn("tcp support not compiled in");
1001 1001
 		#endif
... ...
@@ -1003,7 +1012,7 @@ assign_stm:
1003 1003
 	| TCP_OPT_KEEPINTVL EQUAL error { yyerror("number expected"); }
1004 1004
 	| TCP_OPT_KEEPCNT EQUAL NUMBER {
1005 1005
 		#ifdef USE_TCP
1006
-			tcp_options.keepcnt=$3;
1006
+			tcp_default_cfg.keepcnt=$3;
1007 1007
 		#else
1008 1008
 			warn("tcp support not compiled in");
1009 1009
 		#endif
... ...
@@ -1011,7 +1020,7 @@ assign_stm:
1011 1011
 	| TCP_OPT_KEEPCNT EQUAL error { yyerror("number expected"); }
1012 1012
 	| TCP_OPT_CRLF_PING EQUAL NUMBER {
1013 1013
 		#ifdef USE_TCP
1014
-			tcp_options.crlf_ping=$3;
1014
+			tcp_default_cfg.crlf_ping=$3;
1015 1015
 		#else
1016 1016
 			warn("tcp support not compiled in");
1017 1017
 		#endif
... ...
@@ -41,6 +41,7 @@
41 41
 #include "core_cmd.h"
42 42
 #ifdef USE_SCTP
43 43
 #include "sctp_options.h"
44
+#include "sctp_server.h"
44 45
 #endif
45 46
 
46 47
 #ifdef USE_DNS_CACHE
... ...
@@ -561,19 +562,23 @@ static void core_tcp_options(rpc_t* rpc, void* c)
561 561
 {
562 562
 #ifdef USE_TCP
563 563
 	void *handle;
564
-	struct tcp_cfg_options t;
564
+	struct cfg_group_tcp t;
565 565
 
566 566
 	if (!tcp_disable){
567 567
 		tcp_options_get(&t);
568 568
 		rpc->add(c, "{", &handle);
569
-		rpc->struct_add(handle, "ddddddddddddddd",
569
+		rpc->struct_add(handle, "ddddddddddddddddddddddd",
570
+			"connect_timeout", t.connect_timeout_s,
571
+			"send_timeout",  t.send_timeout_s,
572
+			"connection_lifetime",  t.con_lifetime_s,
573
+			"max_connections(soft)", t.max_connections,
574
+			"no_connect",	t.no_connect,
570 575
 			"fd_cache",		t.fd_cache,
571
-			"tcp_buf_write",	t.tcp_buf_write,
572
-			"tcp_connect_wait",	t.tcp_connect_wait,
573
-			"tcpconn_wq_max",	t.tcpconn_wq_max,
574
-			"tcp_wq_max",	t.tcp_wq_max,
575
-			"tcp_wq_timeout",	TICKS_TO_S(t.tcp_wq_timeout),
576
-			
576
+			"async",		t.async,
577
+			"connect_wait",	t.tcp_connect_wait,
578
+			"conn_wq_max",	t.tcpconn_wq_max,
579
+			"wq_max",		t.tcp_wq_max,
580
+			"wq_timeout",	TICKS_TO_S(t.tcp_wq_timeout),
577 581
 			"defer_accept",	t.defer_accept,
578 582
 			"delayed_ack",	t.delayed_ack,
579 583
 			"syncnt",		t.syncnt,
... ...
@@ -582,7 +587,10 @@ static void core_tcp_options(rpc_t* rpc, void* c)
582 582
 			"keepidle",		t.keepidle,
583 583
 			"keepintvl",	t.keepintvl,
584 584
 			"keepcnt",		t.keepcnt,
585
-			"crlf_ping",	t.crlf_ping
585
+			"crlf_ping",	t.crlf_ping,
586
+			"accept_aliases", t.accept_aliases,
587
+			"alias_flags",	t.alias_flags,
588
+			"new_conn_alias_flags",	t.new_conn_alias_flags
586 589
 		);
587 590
 	}else{
588 591
 		rpc->fault(c, 500, "tcp support disabled");
... ...
@@ -624,6 +632,35 @@ static void core_sctp_options(rpc_t* rpc, void* c)
624 624
 
625 625
 
626 626
 
627
+static const char* core_sctpinfo_doc[] = {
628
+	"Returns sctp related info.",    /* Documentation string */
629
+	0                               /* Method signature(s) */
630
+};
631
+
632
+static void core_sctpinfo(rpc_t* rpc, void* c)
633
+{
634
+#ifdef USE_SCTP
635
+	void *handle;
636
+	struct sctp_gen_info i;
637
+
638
+	if (!sctp_disable){
639
+		sctp_get_info(&i);
640
+		rpc->add(c, "{", &handle);
641
+		rpc->struct_add(handle, "ddd",
642
+			"opened_connections", i.sctp_connections_no,
643
+			"tracked_connections", i.sctp_tracked_no,
644
+			"total_connections", i.sctp_total_connections
645
+		);
646
+	}else{
647
+		rpc->fault(c, 500, "sctp support disabled");
648
+	}
649
+#else
650
+	rpc->fault(c, 500, "sctp support not compiled");
651
+#endif
652
+}
653
+
654
+
655
+
627 656
 /*
628 657
  * RPC Methods exported by this module
629 658
  */
... ...
@@ -646,6 +683,7 @@ rpc_export_t core_rpc_methods[] = {
646 646
 	{"core.tcp_options",       core_tcp_options,       core_tcp_options_doc,0},
647 647
 	{"core.sctp_options",      core_sctp_options,      core_sctp_options_doc,
648 648
 		0},
649
+	{"core.sctp_info",         core_sctpinfo,          core_sctpinfo_doc,   0},
649 650
 #ifdef USE_DNS_CACHE
650 651
 	{"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0	},
651 652
 	{"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0	},
... ...
@@ -641,11 +641,20 @@ int forward_reply(struct sip_msg* msg)
641 641
 	dst.comp=msg->via2->comp_no;
642 642
 #endif
643 643
 
644
+#if defined USE_TCP || defined USE_SCTP
645
+	if (
644 646
 #ifdef USE_TCP
645
-	if (dst.proto==PROTO_TCP
647
+			dst.proto==PROTO_TCP
646 648
 #ifdef USE_TLS
647 649
 			|| dst.proto==PROTO_TLS
648 650
 #endif
651
+#ifdef USE_SCTP
652
+			||
653
+#endif /* USE_SCTP */
654
+#endif /* USE_TCP */
655
+#ifdef USE_SCTP
656
+			dst.proto==PROTO_SCTP
657
+#endif /* USE_SCTP */
649 658
 			){
650 659
 		/* find id in i param if it exists */
651 660
 		if (msg->via1->i && msg->via1->i->value.s){
... ...
@@ -87,12 +87,8 @@ extern int children_no;
87 87
 extern int tcp_main_pid;
88 88
 extern int tcp_children_no;
89 89
 extern int tcp_disable;
90
-extern int tcp_accept_aliases;
91
-extern int tcp_connect_timeout;
92
-extern int tcp_send_timeout;
93
-extern int tcp_con_lifetime; /* connection lifetime */
94 90
 extern enum poll_types tcp_poll_method;
95
-extern int tcp_max_connections;
91
+extern int tcp_max_connections; /* maximum connections, hard limit */
96 92
 #endif
97 93
 #ifdef USE_TLS
98 94
 extern int tls_disable;
... ...
@@ -1621,6 +1621,10 @@ int main(int argc, char** argv)
1621 1621
 		}
1622 1622
 	}
1623 1623
 
1624
+	if (endianness_sanity_check() != 0){
1625
+		fprintf(stderr, "BUG: endianness sanity tests failed\n");
1626
+		goto error;
1627
+	}
1624 1628
 	if (init_routes()<0) goto error;
1625 1629
 	if (init_nonsip_hooks()<0) goto error;
1626 1630
 
... ...
@@ -1926,6 +1930,27 @@ try_again:
1926 1926
 		goto error;
1927 1927
 	if (init_atomic_ops()==-1)
1928 1928
 		goto error;
1929
+	if (init_basex() != 0){
1930
+		LOG(L_CRIT, "could not initialize base* framework\n");
1931
+		goto error;
1932
+	}
1933
+	if (cfg_init() < 0) {
1934
+		LOG(L_CRIT, "could not initialize configuration framework\n");
1935
+		goto error;
1936
+	}
1937
+	/* declare the core cfg before the module configs */
1938
+	if (cfg_declare("core", core_cfg_def, &default_core_cfg, cfg_sizeof(core),
1939
+			&core_cfg)
1940
+	) {
1941
+		LOG(L_CRIT, "could not declare the core configuration\n");
1942
+		goto error;
1943
+	}
1944
+#ifdef USE_TCP
1945
+	if (tcp_register_cfg()){
1946
+		LOG(L_CRIT, "could not register the tcp configuration\n");
1947
+		goto error;
1948
+	}
1949
+#endif /* USE_TCP */
1929 1950
 	/*init timer, before parsing the cfg!*/
1930 1951
 	if (init_timer()<0){
1931 1952
 		LOG(L_CRIT, "could not initialize timer, exiting...\n");
... ...
@@ -1969,6 +1994,14 @@ try_again:
1969 1969
 		}
1970 1970
 	}
1971 1971
 #endif /* USE_TCP */
1972
+#ifdef USE_SCTP
1973
+	if (!sctp_disable){
1974
+		if (init_sctp()<0){
1975
+			LOG(L_CRIT, "Could not initialize sctp, exiting...\n");
1976
+			goto error;
1977
+		}
1978
+	}
1979
+#endif /* USE_SCTP */
1972 1980
 	/* init_daemon? */
1973 1981
 	if (!dont_fork){
1974 1982
 		if ( daemonize(argv[0]) <0 ) goto error;
... ...
@@ -1993,27 +2026,6 @@ try_again:
1993 1993
 			set_rt_prio(rt_prio, rt_policy);
1994 1994
 
1995 1995
 	
1996
-	if (cfg_init() < 0) {
1997
-		LOG(L_CRIT, "could not initialize configuration framework\n");
1998
-		goto error;
1999
-	}
2000
-	/* declare the core cfg before the module configs */
2001
-	if (cfg_declare("core", core_cfg_def, &default_core_cfg, cfg_sizeof(core),
2002
-			&core_cfg)
2003
-	) {
2004
-		LOG(L_CRIT, "could not declare the core configuration\n");
2005
-		goto error;
2006
-	}
2007
-
2008
-	if (endianness_sanity_check() != 0){
2009
-		LOG(L_CRIT, "BUG: endianness sanity tests failed\n");
2010
-		goto error;
2011
-	}
2012
-	if (init_basex() != 0){
2013
-		LOG(L_CRIT, "could not initialize base* framework\n");
2014
-		goto error;
2015
-	}
2016
-	
2017 1996
 	if (init_modules() != 0) {
2018 1997
 		fprintf(stderr, "ERROR: error while initializing modules\n");
2019 1998
 		goto error;
... ...
@@ -2287,7 +2287,7 @@ char* create_via_hf( unsigned int *len,
2287 2287
 	char* via;
2288 2288
 	str extra_params;
2289 2289
 	struct hostport hp;
2290
-#ifdef USE_TCP
2290
+#if defined USE_TCP || defined USE_SCTP
2291 2291
 	char* id_buf;
2292 2292
 	unsigned int id_len;
2293 2293
 
... ...
@@ -2299,13 +2299,21 @@ char* create_via_hf( unsigned int *len,
2299 2299
 	extra_params.s=0;
2300 2300
 
2301 2301
 
2302
-#ifdef USE_TCP
2302
+#if defined USE_TCP || defined USE_SCTP
2303 2303
 	/* add id if tcp */
2304
-	if (msg
2305
-	&& ((msg->rcv.proto==PROTO_TCP)
2304
+	if (msg && (
2305
+#ifdef USE_TCP
2306
+		(msg->rcv.proto==PROTO_TCP)
2306 2307
 #ifdef USE_TLS
2307 2308
 			|| (msg->rcv.proto==PROTO_TLS)
2308 2309
 #endif
2310
+#ifdef USE_SCTP
2311
+			||
2312
+#endif /* USE_SCTP */
2313
+#endif /* USE_TCP */
2314
+#ifdef USE_SCTP
2315
+			(msg->rcv.proto==PROTO_SCTP)
2316
+#endif /* USE_SCTP */
2309 2317
 			)){
2310 2318
 		if  ((id_buf=id_builder(msg, &id_len))==0){
2311 2319
 			LOG(L_ERR, "ERROR: create_via_hf:"
... ...
@@ -2318,13 +2326,13 @@ char* create_via_hf( unsigned int *len,
2318 2318
 		extra_params.s=id_buf;
2319 2319
 		extra_params.len=id_len;
2320 2320
 	}
2321
-#endif
2321
+#endif /* USE_TCP || USE_SCTP */
2322 2322
 
2323 2323
 	set_hostport(&hp, msg);
2324 2324
 	via = via_builder( len, send_info, branch,
2325 2325
 							extra_params.len?&extra_params:0, &hp);
2326 2326
 
2327
-#ifdef USE_TCP
2327
+#if defined USE_TCP || defined USE_SCTP
2328 2328
 	/* we do not need id_buf any more, the id is already in the new via header */
2329 2329
 	if (id_buf) pkg_free(id_buf);
2330 2330
 #endif
... ...
@@ -62,7 +62,8 @@
62 62
 #include "select_buf.h"
63 63
 
64 64
 #include "tcp_server.h" /* for tcpconn_add_alias */
65
-
65
+#include "tcp_options.h" /* for access to tcp_accept_aliases*/
66
+#include "cfg/cfg.h"
66 67
 
67 68
 #ifdef DEBUG_DMALLOC
68 69
 #include <mem/dmalloc.h>
... ...
@@ -138,7 +139,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
138 138
 		/* check if necessary to add receive?->moved to forward_req */
139 139
 		/* check for the alias stuff */
140 140
 #ifdef USE_TCP
141
-		if (msg->via1->alias && tcp_accept_aliases && 
141
+		if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) && 
142 142
 				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
143 143
 #ifdef USE_TLS
144 144
 					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
... ...
@@ -53,9 +53,15 @@
53 53
 #ifdef USE_DST_BLACKLIST
54 54
 #include "dst_blacklist.h"
55 55
 #endif /* USE_DST_BLACKLIST */
56
+#include "timer_ticks.h"
57
+#include "clist.h"
58
+#include "error.h"
59
+#include "timer.h"
56 60
 
57 61
 
58 62
 
63
+static atomic_t* sctp_conn_no;
64
+
59 65
 /* check if the underlying OS supports sctp
60 66
    returns 0 if yes, -1 on error */
61 67
 int sctp_check_support()
... ...
@@ -521,6 +527,1004 @@ error:
521 521
 #endif /* USE_SCTP_OO */
522 522
 
523 523
 
524
+#define SCTP_CONN_REUSE /* FIXME */
525
+#ifdef SCTP_CONN_REUSE
526
+
527
+/* we  need SCTP_ADDR_HASH for being able to make inquires related to existing
528
+   sctp association to a particular address  (optional) */
529
+/*#define SCTP_ADDR_HASH*/
530
+
531
+#define SCTP_ID_HASH_SIZE 1024 /* must be 2^k */
532
+#define SCTP_ASSOC_HASH_SIZE 1024 /* must be 2^k */
533
+#define SCTP_ADDR_HASH_SIZE 1024 /* must be 2^k */
534
+
535
+/* lock method */
536
+#ifdef GEN_LOCK_T_UNLIMITED
537
+#define SCTP_HASH_LOCK_PER_BUCKET
538
+#elif defined GEN_LOCK_SET_T_UNLIMITED
539
+#define SCTP_HASH_LOCK_SET
540
+#else
541
+#define SCTP_HASH_ONE_LOCK
542
+#endif
543
+
544
+
545
+#ifdef SCTP_HASH_LOCK_PER_BUCKET
546
+/* lock included in the hash bucket */
547
+#define LOCK_SCTP_ID_H(h)		lock_get(&sctp_con_id_hash[(h)].lock)
548
+#define UNLOCK_SCTP_ID_H(h)		lock_release(&sctp_con_id_hash[(h)].lock)
549
+#define LOCK_SCTP_ASSOC_H(h)	lock_get(&sctp_con_assoc_hash[(h)].lock)
550
+#define UNLOCK_SCTP_ASSOC_H(h)	lock_release(&sctp_con_assoc_hash[(h)].lock)
551
+#define LOCK_SCTP_ADDR_H(h)		lock_get(&sctp_con_addr_hash[(h)].lock)
552
+#define UNLOCK_SCTP_ADDR_H(h)	lock_release(&sctp_con_addr_hash[(h)].lock)
553
+#elif defined SCTP_HASH_LOCK_SET
554
+static gen_lock_set_t* sctp_con_id_h_lock_set=0;
555
+static gen_lock_set_t* sctp_con_assoc_h_lock_set=0;
556
+static gen_lock_set_t* sctp_con_addr_h_lock_set=0;
557
+#define LOCK_SCTP_ID_H(h)		lock_set_get(sctp_con_id_h_lock_set, (h))
558
+#define UNLOCK_SCTP_ID_H(h)		lock_set_release(sctp_con_id_h_lock_set, (h))
559
+#define LOCK_SCTP_ASSOC_H(h)	lock_set_get(sctp_con_assoc_h_lock_set, (h))
560
+#define UNLOCK_SCTP_ASSOC_H(h)	\
561
+	lock_set_release(sctp_con_assoc_h_lock_set, (h))
562
+#define LOCK_SCTP_ADDR_H(h)	lock_set_get(sctp_con_addr_h_lock_set, (h))
563
+#define UNLOCK_SCTP_ADDR_H(h)	lock_set_release(sctp_con_addr_h_lock_set, (h))
564
+#else /* use only one lock */
565
+static gen_lock_t* sctp_con_id_h_lock=0;
566
+static gen_lock_t* sctp_con_assoc_h_lock=0;
567
+static gen_lock_t* sctp_con_addr_h_lock=0;
568
+#define LOCK_SCTP_ID_H(h)		lock_get(sctp_con_id_h_lock)
569
+#define UNLOCK_SCTP_ID_H(h)		lock_release(sctp_con_id_hlock)
570
+#define LOCK_SCTP_ASSOC_H(h)	lock_get(sctp_con_assoc_h_lock)
571
+#define UNLOCK_SCTP_ASSOC_H(h)	lock_release(sctp_con_assoc_h_lock)
572
+#define LOCK_SCTP_ADDR_H(h)	lock_get(sctp_con_addr_h_lock)
573
+#define UNLOCK_SCTP_ADDR_H(h)	lock_release(sctp_con_addr_h_lock)
574
+#endif /* SCTP_HASH_LOCK_PER_BUCKET */
575
+
576
+
577
+/* sctp connection flags */
578
+#define SCTP_CON_UP_SEEN   1
579
+#define SCTP_CON_RCV_SEEN  2
580
+#define SCTP_CON_DOWN_SEEN 4
581
+
582
+struct sctp_connection{
583
+	unsigned int id;       /**< ser unique global id */
584
+	unsigned int assoc_id; /**< sctp assoc id (can be reused for new assocs)*/
585
+	struct socket_info* si; /**< local socket used */
586
+	unsigned flags; /**< internal flags UP_SEEN, RCV_SEEN, DOWN_SEEN */
587
+	ticks_t start;
588
+	ticks_t expire; 
589
+	union sockaddr_union remote; /**< remote ip & port */
590
+};
591
+
592
+struct sctp_lst_connector{
593
+	/* id hash */
594
+	struct sctp_con_elem* next_id;
595
+	struct sctp_con_elem* prev_id;
596
+	/* assoc hash */
597
+	struct sctp_con_elem* next_assoc;
598
+	struct sctp_con_elem* prev_assoc;
599
+#ifdef SCTP_ADDR_HASH
600
+	/* addr hash */
601
+	struct sctp_con_elem* next_addr;
602
+	struct sctp_con_elem* prev_addr;
603
+#endif /* SCTP_ADDR_HASH */
604
+};
605
+
606
+struct sctp_con_elem{
607
+	struct sctp_lst_connector l; /* must be first */
608
+	atomic_t refcnt;
609
+	/* data */
610
+	struct sctp_connection con;
611
+};
612
+
613
+struct sctp_con_id_hash_head{
614
+	struct sctp_lst_connector l; /* must be first */
615
+#ifdef SCTP_HASH_LOCK_PER_BUCKET
616
+	gen_lock_t lock;
617
+#endif /* SCTP_HASH_LOCK_PER_BUCKET */
618
+};
619
+
620
+struct sctp_con_assoc_hash_head{
621
+	struct sctp_lst_connector l; /* must be first */
622
+#ifdef SCTP_HASH_LOCK_PER_BUCKET
623
+	gen_lock_t lock;
624
+#endif /* SCTP_HASH_LOCK_PER_BUCKET */
625
+};
626
+
627
+#ifdef SCTP_ADDR_HASH
628
+struct sctp_con_addr_hash_head{
629
+	struct sctp_lst_connector l; /* must be first */
630
+#ifdef SCTP_HASH_LOCK_PER_BUCKET
631
+	gen_lock_t lock;
632
+#endif /* SCTP_HASH_LOCK_PER_BUCKET */
633
+};
634
+#endif /* SCTP_ADDR_HASH */
635
+
636
+static struct sctp_con_id_hash_head*     sctp_con_id_hash;
637
+static struct sctp_con_assoc_hash_head*  sctp_con_assoc_hash;
638
+#ifdef SCTP_ADDR_HASH
639
+static struct sctp_con_addr_hash_head*  sctp_con_addr_hash;
640
+#endif /* SCTP_ADDR_HASH */
641
+
642
+static atomic_t* sctp_id;
643
+static atomic_t* sctp_conn_tracked;
644
+
645
+
646
+#define get_sctp_con_id_hash(id) ((id) % SCTP_ID_HASH_SIZE)
647
+#define get_sctp_con_assoc_hash(assoc_id)  ((assoc_id) % SCTP_ASSOC_HASH_SIZE)
648
+#ifdef SCTP_ADDR_HASH
649
+static inline unsigned get_sctp_con_addr_hash(union sockaddr_union* remote,
650
+											struct socket_info* si)
651
+{
652
+	struct ip_addr ip;
653
+	unsigned short port;
654
+	unsigned h;
655
+	
656
+	su2ip_addr(&ip, remote);
657
+	port=su_getport(remote);
658
+	if (likely(ip.len==4))
659
+		h=ip.u.addr32[0]^port;
660
+	else if (ip.len==16)
661
+		h=ip.u.addr32[0]^ip.u.addr32[1]^ip.u.addr32[2]^ ip.u.addr32[3]^port;
662
+	else
663
+		h=0; /* error */
664
+	/* make sure the first bits are influenced by all 32
665
+	 * (the first log2(SCTP_ADDR_HASH_SIZE) bits should be a mix of all
666
+	 *  32)*/
667
+	h ^= h>>17;
668
+	h ^= h>>7;
669
+	return h & (SCTP_ADDR_HASH_SIZE-1);
670
+}
671
+#endif /* SCTP_ADDR_HASH */
672
+
673
+
674
+
675
+/** destroy sctp conn hashes. */
676
+void destroy_sctp_con_tracking()
677
+{
678
+	int r;
679
+	
680
+#ifdef SCTP_HASH_LOCK_PER_BUCKET
681
+	if (sctp_con_id_hash)
682
+		for(r=0; r<SCTP_ID_HASH_SIZE; r++)
683
+			lock_destroy(&sctp_con_id_hash[r].lock);
684
+	if (sctp_con_assoc_hash)
685
+		for(r=0; r<SCTP_ASSOC_HASH_SIZE; r++)
686
+			lock_destroy(&sctp_con_assoc_hash[r].lock);
687
+#	ifdef SCTP_ADDR_HASH
688
+	if (sctp_con_addr_hash)
689
+		for(r=0; r<SCTP_ADDR_HASH_SIZE; r++)
690
+			lock_destroy(&sctp_con_addr_hash[r].lock);
691
+#	endif /* SCTP_ADDR_HASH */
692
+#elif defined SCTP_HASH_LOCK_SET
693
+	if (sctp_con_id_h_lock_set){
694
+		lock_set_destroy(sctp_con_id_h_lock_set);
695
+		lock_set_dealloc(sctp_con_id_h_lock_set);
696
+		sctp_con_id_h_lock_set=0;
697
+	}
698
+	if (sctp_con_assoc_h_lock_set){
699
+		lock_set_destroy(sctp_con_assoc_h_lock_set);
700
+		lock_set_dealloc(sctp_con_assoc_h_lock_set);
701
+		sctp_con_assoc_h_lock_set=0;
702
+	}
703
+#	ifdef SCTP_ADDR_HASH
704
+	if (sctp_con_addr_h_lock_set){
705
+		lock_set_destroy(sctp_con_addr_h_lock_set);
706
+		lock_set_dealloc(sctp_con_addr_h_lock_set);
707
+		sctp_con_addr_h_lock_set=0;
708
+	}
709
+#	endif /* SCTP_ADDR_HASH */
710
+#else /* SCTP_HASH_ONE_LOCK */
711
+	if (sctp_con_id_h_lock){
712
+		lock_destroy(sctp_con_id_h_lock);
713
+		lock_dealloc(sctp_con_id_h_lock);
714
+		sctp_con_id_h_lock=0;
715
+	}
716
+	if (sctp_con_assoc_h_lock){
717
+		lock_destroy(sctp_con_assoc_h_lock);
718
+		lock_dealloc(sctp_con_assoc_h_lock);
719
+		sctp_con_assoc_h_lock=0;
720
+	}
721
+#	ifdef SCTP_ADDR_HASH
722
+	if (sctp_con_addr_h_lock){
723
+		lock_destroy(sctp_con_addr_h_lock);
724
+		lock_dealloc(sctp_con_addr_h_lock);
725
+		sctp_con_addr_h_lock=0;
726
+	}
727
+#	endif /* SCTP_ADDR_HASH */
728
+#endif /* SCTP_HASH_LOCK_PER_BUCKET/SCTP_HASH_LOCK_SET/one lock */
729
+	if (sctp_con_id_hash){
730
+		shm_free(sctp_con_id_hash);
731
+		sctp_con_id_hash=0;
732
+	}
733
+	if (sctp_con_assoc_hash){
734
+		shm_free(sctp_con_assoc_hash);
735
+		sctp_con_assoc_hash=0;
736
+	}
737
+#ifdef SCTP_ADDR_HASH
738
+	if (sctp_con_addr_hash){
739
+		shm_free(sctp_con_addr_hash);
740
+		sctp_con_addr_hash=0;
741
+	}
742
+#endif /* SCTP_ADDR_HASH */
743
+	if (sctp_id){
744
+		shm_free(sctp_id);
745
+		sctp_id=0;
746
+	}
747
+	if (sctp_conn_tracked){
748
+		shm_free(sctp_conn_tracked);
749
+		sctp_conn_tracked=0;
750
+	}
751
+}
752
+
753
+
754
+
755
+/** intializaze sctp_conn hashes.
756
+  * @return 0 on success, <0 on error
757
+  */
758
+int init_sctp_con_tracking()
759
+{
760
+	int r, ret;
761
+	
762
+	sctp_con_id_hash=shm_malloc(SCTP_ID_HASH_SIZE*sizeof(*sctp_con_id_hash));
763
+	sctp_con_assoc_hash=shm_malloc(SCTP_ASSOC_HASH_SIZE*
764
+									sizeof(*sctp_con_assoc_hash));
765
+#ifdef SCTP_ADDR_HASH
766
+	sctp_con_addr_hash=shm_malloc(SCTP_ADDR_HASH_SIZE*
767
+									sizeof(*sctp_con_addr_hash));
768
+#endif /* SCTP_ADDR_HASH */
769
+	sctp_id=shm_malloc(sizeof(*sctp_id));
770
+	sctp_conn_tracked=shm_malloc(sizeof(*sctp_conn_tracked));
771
+	if (sctp_con_id_hash==0 || sctp_con_assoc_hash==0 ||
772
+#ifdef SCTP_ADDR_HASH
773
+			sctp_con_addr_hash==0 ||
774
+#endif /* SCTP_ADDR_HASH */
775
+			sctp_id==0 || sctp_conn_tracked==0){
776
+		ERR("sctp init: memory allocation error\n");
777
+		ret=E_OUT_OF_MEM;
778
+		goto error;
779
+	}
780
+	atomic_set(sctp_id, 0);
781
+	atomic_set(sctp_conn_tracked, 0);
782
+	for (r=0; r<SCTP_ID_HASH_SIZE; r++)
783
+		clist_init(&sctp_con_id_hash[r], l.next_id, l.prev_id);
784
+	for (r=0; r<SCTP_ASSOC_HASH_SIZE; r++)
785
+		clist_init(&sctp_con_assoc_hash[r], l.next_assoc, l.prev_assoc);
786
+#ifdef SCTP_ADDR_HASH
787
+	for (r=0; r<SCTP_ADDR_HASH_SIZE; r++)
788
+		clist_init(&sctp_con_addr_hash[r], l.next_addr, l.prev_addr);
789
+#endif /* SCTP_ADDR_HASH */
790
+#ifdef SCTP_HASH_LOCK_PER_BUCKET
791
+	for (r=0; r<SCTP_ID_HASH_SIZE; r++){
792
+		if (lock_init(&sctp_con_id_hash[r].lock)==0){
793
+			ret=-1;
794
+			ERR("sctp init: failed to initialize locks\n");
795
+			goto error;
796
+		}
797
+	}
798
+	for (r=0; r<SCTP_ASSOC_HASH_SIZE; r++){
799
+		if (lock_init(&sctp_con_assoc_hash[r].lock)==0){
800
+			ret=-1;
801
+			ERR("sctp init: failed to initialize locks\n");
802
+			goto error;
803
+		}
804
+	}
805
+#	ifdef SCTP_ADDR_HASH
806
+	for (r=0; r<SCTP_ADDR_HASH_SIZE; r++){
807
+		if (lock_init(&sctp_con_addr_hash[r].lock)==0){
808
+			ret=-1;
809
+			ERR("sctp init: failed to initialize locks\n");
810
+			goto error;
811
+		}
812
+	}
813
+#	endif /* SCTP_ADDR_HASH */
814
+#elif defined SCTP_HASH_LOCK_SET
815
+	sctp_con_id_h_lock_set=lock_set_alloc(SCTP_ID_HASH_SIZE);
816
+	sctp_con_assoc_h_lock_set=lock_set_alloc(SCTP_ASSOC_HASH_SIZE);
817
+#	ifdef SCTP_ADDR_HASH
818
+	sctp_con_addr_h_lock_set=lock_set_alloc(SCTP_ADDR_HASH_SIZE);
819
+#	endif /* SCTP_ADDR_HASH */
820
+	if (sctp_con_id_h_lock_set==0 || sctp_con_assoc_h_lock_set==0
821
+#	ifdef SCTP_ADDR_HASH
822
+			|| sctp_con_addr_h_lock_set==0
823
+#	endif /* SCTP_ADDR_HASH */
824
+			){
825
+		ret=E_OUT_OF_MEM;
826
+		ERR("sctp_init: failed to alloc lock sets\n");
827
+		goto error;
828
+	}
829
+	if (lock_set_init(sctp_con_id_h_lock_set)==0){
830
+		lock_set_dealloc(sctp_con_id_h_lock_set);
831
+		sctp_con_id_h_lock_set=0;
832
+		ret=-1;
833
+		ERR("sctp init: failed to initialize lock set\n");
834
+		goto error;
835
+	}
836
+	if (lock_set_init(sctp_con_assoc_h_lock_set)==0){
837
+		lock_set_dealloc(sctp_con_assoc_h_lock_set);
838
+		sctp_con_assoc_h_lock_set=0;
839
+		ret=-1;
840
+		ERR("sctp init: failed to initialize lock set\n");
841
+		goto error;
842
+	}
843
+#	ifdef SCTP_ADDR_HASH
844
+	if (lock_set_init(sctp_con_addr_h_lock_set)==0){
845
+		lock_set_dealloc(sctp_con_addr_h_lock_set);
846
+		sctp_con_addr_h_lock_set=0;
847
+		ret=-1;
848
+		ERR("sctp init: failed to initialize lock set\n");
849
+		goto error;
850
+	}
851
+#	endif /* SCTP_ADDR_HASH */
852
+#else /* SCTP_HASH_ONE_LOCK */
853
+	sctp_con_id_h_lock=lock_alloc();
854
+	sctp_con_assoc_h_lock=lock_alloc();
855
+#	ifdef SCTP_ADDR_HASH
856
+	sctp_con_addr_h_lock=lock_alloc();
857
+#	endif /* SCTP_ADDR_HASH */
858
+	if (sctp_con_id_h_lock==0 || sctp_con_assoc_h_lock==0
859
+#	ifdef SCTP_ADDR_HASH
860
+			|| sctp_con_addr_h_lock==0
861
+#	endif /* SCTP_ADDR_HASH */
862
+			){
863
+		ret=E_OUT_OF_MEM;
864
+		ERR("sctp init: failed to alloc locks\n");
865
+		goto error;
866
+	}
867
+	if (lock_init(sctp_con_id_h_lock)==0){
868
+		lock_dealloc(sctp_con_id_h_lock);
869
+		sctp_con_id_h_lock=0;
870
+		ret=-1;
871
+		ERR("sctp init: failed to initialize lock\n");
872
+		goto error;
873
+	}
874
+	if (lock_init(sctp_con_assoc_h_lock)==0){
875
+		lock_dealloc(sctp_con_assoc_h_lock);
876
+		sctp_con_assoc_h_lock=0;
877
+		ret=-1;
878
+		ERR("sctp init: failed to initialize lock\n");
879
+		goto error;
880
+	}
881
+#	ifdef SCTP_ADDR_HASH
882
+	if (lock_init(sctp_con_addr_h_lock)==0){
883
+		lock_dealloc(sctp_con_addr_h_lock);
884
+		sctp_con_addr_h_lock=0;
885
+		ret=-1;
886
+		ERR("sctp init: failed to initialize lock\n");
887
+		goto error;
888
+	}
889
+#	endif /* SCTP_ADDR_HASH */
890
+#endif /* SCTP_HASH_LOCK_PER_BUCKET/SCTP_HASH_LOCK_SET/one lock */
891
+	return 0;
892
+error:
893
+	destroy_sctp_con_tracking();
894
+	return ret;
895
+}
896
+
897
+
898
+
899
+#if 0
900
+/** adds "e" to the hashes, safe locking version.*/
901
+static void sctp_con_add(struct sctp_con_elem* e)
902
+{
903
+	unsigned hash;
904
+	DBG("sctp_con_add(%p) ( ser id %d, assoc_id %d)\n",
905
+			e, e->con.id, e->con.assoc_id);
906
+	
907
+	e->l.next_id=e->l.prev_id=0;
908
+	e->l.next_assoc=e->l.prev_assoc=0;
909
+#ifdef SCTP_ADDR_HASH
910
+	e->l.next_addr=e->l.prev_addr=0;
911
+	e->refcnt.val+=3; /* account for the 3 lists */
912
+#else /* SCTP_ADDR_HASH */
913
+	e->refcnt.val+=2; /* account for the 2 lists */
914
+#endif /* SCTP_ADDR_HASH */
915
+	hash=get_sctp_con_id_hash(e->con.id);
916
+	DBG("adding to con id hash %d\n", hash);
917
+	LOCK_SCTP_ID_H(hash);
918
+		clist_insert(&sctp_con_id_hash[hash], e, l.next_id, l.prev_id);
919
+	UNLOCK_SCTP_ID_H(hash);
920
+	hash=get_sctp_con_assoc_hash(e->con.assoc_id);
921
+	DBG("adding to assoc_id hash %d\n", hash);
922
+	LOCK_SCTP_ASSOC_H(hash);
923
+		clist_insert(&sctp_con_assoc_hash[hash], e,
924
+						l.next_assoc, l.prev_assoc);
925
+	UNLOCK_SCTP_ASSOC_H(hash);
926
+#ifdef SCTP_ADDR_HASH
927
+	hash=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
928
+	DBG("adding to addr hash %d\n", hash);
929
+	LOCK_SCTP_ADDR_H(hash);
930
+		clist_insert(&sctp_con_addr_hash[hash], e,
931
+						l.next_addr, l.prev_addr);
932
+	UNLOCK_SCTP_ADDR_H(hash);
933
+#endif /* SCTP_ADDR_HASH */
934
+	atomic_inc(sctp_conn_tracked);
935
+}
936
+#endif
937
+
938
+
939
+
940
+/** helper internal del elem function, the id hash must be locked.
941
+  * WARNING: the id hash(h) _must_ be locked (LOCK_SCTP_ID_H(h)).
942
+  * @param h - id hash
943
+  * @param e - sctp_con_elem to delete (from all the hashes)
944
+  * @return 0 if the id hash was unlocked, 1 if it's still locked */
945
+inline static int _sctp_con_del_id_locked(unsigned h, struct sctp_con_elem* e)
946
+{
947
+	unsigned assoc_id_h;
948
+	int deref; /* delayed de-reference counter */
949
+	int locked;
950
+#ifdef SCTP_ADDR_HASH
951
+	unsigned addr_h;
952
+#endif /* SCTP_ADDR_HASH */
953
+	
954
+	locked=1;
955
+	clist_rm(e, l.next_id, l.prev_id);
956
+	e->l.next_id=e->l.prev_id=0; /* mark it as id unhashed */
957
+	/* delay atomic dereference, so that we'll perform only one
958
+	   atomic op. even for multiple derefs. It also has the
959
+	   nice side-effect that the entry will be guaranteed to be
960
+	   referenced until we perform the delayed deref. at the end,
961
+	   so we don't need to keep some lock to prevent somebody from
962
+	   deleting the entry from under us */
963
+	deref=1; /* removed from one list =>  deref once */
964
+	/* remove it from the assoc hash if needed */
965
+	if (likely(e->l.next_assoc)){
966
+		UNLOCK_SCTP_ID_H(h);
967
+		locked=0; /* no longer id-locked */
968
+		/* we haven't dec. refcnt, so it's still safe to use e */
969
+		assoc_id_h=get_sctp_con_assoc_hash(e->con.assoc_id);
970
+		LOCK_SCTP_ASSOC_H(assoc_id_h);
971
+			/* make sure nobody removed it in the meantime */
972
+			if (likely(e->l.next_assoc)){
973
+				clist_rm(e, l.next_assoc, l.prev_assoc);
974
+				e->l.next_assoc=e->l.prev_assoc=0; /* mark it as removed */
975
+				deref++; /* rm'ed from the assoc list => inc. delayed deref. */
976
+			}
977
+		UNLOCK_SCTP_ASSOC_H(assoc_id_h);
978
+	}
979
+#ifdef SCTP_ADDR_HASH
980
+	/* remove it from the addr. hash if needed */
981
+	if (likely(e->l.next_addr)){
982
+		if (unlikely(locked)){
983
+			UNLOCK_SCTP_ID_H(h);
984
+			locked=0; /* no longer id-locked */
985
+		}
986
+		addr_h=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
987
+		LOCK_SCTP_ADDR_H(addr_h);
988
+			/* make sure nobody removed it in the meantime */
989
+			if (likely(e->l.next_addr)){
990
+				clist_rm(e, l.next_addr, l.prev_addr);
991
+				e->l.next_addr=e->l.prev_addr=0; /* mark it as removed */
992
+				deref++; /* rm'ed from the addr list => inc. delayed deref. */
993
+			}
994
+		UNLOCK_SCTP_ADDR_H(addr_h);
995
+	}
996
+#endif /* SCTP_ADDR_HASH */
997
+	
998
+	/* performed delayed de-reference */
999
+	if (atomic_add(&e->refcnt, -deref)==0){
1000
+		atomic_dec(sctp_conn_tracked);
1001
+		shm_free(e);
1002
+	}
1003
+	else
1004
+		DBG("del assoc post-deref (kept): ser id %d, assoc_id %d,"
1005
+			" post-refcnt %d, deref %d, post-tracked %d\n",
1006
+			e->con.id, e->con.assoc_id, atomic_get(&e->refcnt), deref,
1007
+			atomic_get(sctp_conn_tracked));
1008
+	return locked;
1009
+}
1010
+
1011
+
1012
+
1013
+/** helper internal del elem function, the assoc hash must be locked.
1014
+  * WARNING: the assoc hash(h) _must_ be locked (LOCK_SCTP_ASSOC_H(h)).
1015
+  * @param h - assoc hash
1016
+  * @param e - sctp_con_elem to delete (from all the hashes)
1017
+  * @return 0 if the assoc hash was unlocked, 1 if it's still locked */
1018
+inline static int _sctp_con_del_assoc_locked(unsigned h,
1019
+												struct sctp_con_elem* e)
1020
+{
1021
+	unsigned id_hash;
1022
+	int deref; /* delayed de-reference counter */
1023
+	int locked;
1024
+#ifdef SCTP_ADDR_HASH
1025
+	unsigned addr_h;
1026
+#endif /* SCTP_ADDR_HASH */
1027
+	
1028
+	locked=1;
1029
+	clist_rm(e, l.next_assoc, l.prev_assoc);
1030
+	e->l.next_assoc=e->l.prev_assoc=0; /* mark it as assoc unhashed */
1031
+	/* delay atomic dereference, so that we'll perform only one
1032
+	   atomic op. even for multiple derefs. It also has the
1033
+	   nice side-effect that the entry will be guaranteed to be
1034
+	   referenced until we perform the delayed deref. at the end,
1035
+	   so we don't need to keep some lock to prevent somebody from
1036
+	   deleting the entry from under us */
1037
+	deref=1; /* removed from one list =>  deref once */
1038
+	/* remove it from the id hash if needed */
1039
+	if (likely(e->l.next_id)){
1040
+		UNLOCK_SCTP_ASSOC_H(h);
1041
+		locked=0; /* no longer assoc-hash-locked */
1042
+		/* we have a ref. to it so it's still safe to use e */
1043
+		id_hash=get_sctp_con_id_hash(e->con.id);
1044
+		LOCK_SCTP_ID_H(id_hash);
1045
+			/* make sure nobody removed it in the meantime */
1046
+			if (likely(e->l.next_id)){
1047
+				clist_rm(e, l.next_id, l.prev_id);
1048
+				e->l.next_id=e->l.prev_id=0; /* mark it as removed */
1049
+				deref++; /* rm'ed from the id list => inc. delayed deref. */
1050
+			}
1051
+		UNLOCK_SCTP_ID_H(id_hash);
1052
+	}
1053
+#ifdef SCTP_ADDR_HASH
1054
+	/* remove it from the addr. hash if needed */
1055
+	if (likely(e->l.next_addr)){
1056
+		if (unlikely(locked)){
1057
+			UNLOCK_SCTP_ASSOC_H(h);
1058
+			locked=0; /* no longer id-locked */
1059
+		}
1060
+		addr_h=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
1061
+		LOCK_SCTP_ADDR_H(addr_h);
1062
+			/* make sure nobody removed it in the meantime */
1063
+			if (likely(e->l.next_addr)){
1064
+				clist_rm(e, l.next_addr, l.prev_addr);
1065
+				e->l.next_addr=e->l.prev_addr=0; /* mark it as removed */
1066
+				deref++; /* rm'ed from the addr list => inc. delayed deref. */
1067
+			}
1068
+		UNLOCK_SCTP_ADDR_H(addr_h);
1069
+	}
1070
+#endif /* SCTP_ADDR_HASH */
1071
+	if (atomic_add(&e->refcnt, -deref)==0){
1072
+		atomic_dec(sctp_conn_tracked);
1073
+		shm_free(e);
1074
+	}
1075
+	else
1076
+		DBG("del assoc post-deref (kept): ser id %d, assoc_id %d,"
1077
+				" post-refcnt %d, deref %d, post-tracked %d\n",
1078
+				e->con.id, e->con.assoc_id, atomic_get(&e->refcnt), deref,
1079
+				atomic_get(sctp_conn_tracked));
1080
+	return locked;
1081
+}
1082
+
1083
+
1084
+
1085
+#ifdef SCTP_ADDR_HASH
1086
+/** helper internal del elem function, the addr hash must be locked.
1087
+  * WARNING: the addr hash(h) _must_ be locked (LOCK_SCTP_ADDR_H(h)).
1088
+  * @param h - addr hash
1089
+  * @param e - sctp_con_elem to delete (from all the hashes)
1090
+  * @return 0 if the addr hash was unlocked, 1 if it's still locked */
1091
+inline static int _sctp_con_del_addr_locked(unsigned h,
1092
+												struct sctp_con_elem* e)
1093
+{
1094
+	unsigned id_hash;
1095
+	unsigned assoc_id_h;
1096
+	int deref; /* delayed de-reference counter */
1097
+	int locked;
1098
+	
1099
+	locked=1;
1100
+	clist_rm(e, l.next_addr, l.prev_addr);
1101
+	e->l.next_addr=e->l.prev_addr=0; /* mark it as addr unhashed */
1102
+	/* delay atomic dereference, so that we'll perform only one
1103
+	   atomic op. even for multiple derefs. It also has the
1104
+	   nice side-effect that the entry will be guaranteed to be
1105
+	   referenced until we perform the delayed deref. at the end,
1106
+	   so we don't need to keep some lock to prevent somebody from
1107
+	   deleting the entry from under us */
1108
+	deref=1; /* removed from one list =>  deref once */
1109
+	/* remove it from the id hash if needed */
1110
+	if (likely(e->l.next_id)){
1111
+		UNLOCK_SCTP_ADDR_H(h);
1112
+		locked=0; /* no longer addr-hash-locked */
1113
+		/* we have a ref. to it so it's still safe to use e */
1114
+		id_hash=get_sctp_con_id_hash(e->con.id);
1115
+		LOCK_SCTP_ID_H(id_hash);
1116
+			/* make sure nobody removed it in the meantime */
1117
+			if (likely(e->l.next_id)){
1118
+				clist_rm(e, l.next_id, l.prev_id);
1119
+				e->l.next_id=e->l.prev_id=0; /* mark it as removed */
1120
+				deref++; /* rm'ed from the id list => inc. delayed deref. */
1121
+			}
1122
+		UNLOCK_SCTP_ID_H(id_hash);
1123
+	}
1124
+	/* remove it from the assoc hash if needed */
1125
+	if (likely(e->l.next_assoc)){
1126
+		if (locked){
1127
+			UNLOCK_SCTP_ADDR_H(h);
1128
+			locked=0; /* no longer addr-hash-locked */
1129
+		}
1130
+		/* we haven't dec. refcnt, so it's still safe to use e */
1131
+		assoc_id_h=get_sctp_con_assoc_hash(e->con.assoc_id);
1132
+		LOCK_SCTP_ASSOC_H(assoc_id_h);
1133
+			/* make sure nobody removed it in the meantime */
1134
+			if (likely(e->l.next_assoc)){
1135
+				clist_rm(e, l.next_assoc, l.prev_assoc);
1136
+				e->l.next_assoc=e->l.prev_assoc=0; /* mark it as removed */
1137
+				deref++; /* rm'ed from the assoc list => inc. delayed deref. */
1138
+			}
1139
+		UNLOCK_SCTP_ASSOC_H(assoc_id_h);
1140
+	}
1141
+	if (atomic_add(&e->refcnt, -deref)==0){
1142
+		atomic_dec(sctp_conn_tracked);
1143
+		shm_free(e);
1144
+	}
1145
+	else
1146
+		DBG("del assoc post-deref (kept): ser id %d, assoc_id %d,"
1147
+				" post-refcnt %d, deref %d, post-tracked %d\n",
1148
+				e->con.id, e->con.assoc_id, atomic_get(&e->refcnt), deref,
1149
+				atomic_get(sctp_conn_tracked));
1150
+	return locked;
1151
+}
1152
+#endif /* SCTP_ADDR_HASH */
1153
+
1154
+
1155
+
1156
+/** using id, get the corresponding sctp assoc & socket. 
1157
+ *  @param id - ser unique assoc id
1158
+ *  @param si  - result parameter, filled with the socket info on success
1159
+ *  @param remote - result parameter, filled with the address and port
1160
+ *  @param del - if 1 delete the entry,
1161
+ *  @return assoc_id (!=0) on success & sets si, 0 on not found
1162
+ * si and remote will not be touched on failure.
1163
+ *
1164
+ */
1165
+int sctp_con_get_assoc(unsigned int id, struct socket_info** si, 
1166
+								union sockaddr_union *remote, int del)
1167
+{
1168
+	unsigned h;
1169
+	ticks_t now; 
1170
+	struct sctp_con_elem* e;
1171
+	struct sctp_con_elem* tmp;
1172
+	int ret;
1173
+	
1174
+	ret=0;
1175
+	now=get_ticks_raw();
1176
+	h=get_sctp_con_id_hash(id);
1177
+#if 0
1178
+again:
1179
+#endif
1180
+	LOCK_SCTP_ID_H(h);
1181
+		clist_foreach_safe(&sctp_con_id_hash[h], e, tmp, l.next_id){
1182
+			if(e->con.id==id){
1183
+				ret=e->con.assoc_id;
1184
+				*si=e->con.si;
1185
+				*remote=e->con.remote;
1186
+				if (del){
1187
+					if (_sctp_con_del_id_locked(h, e)==0)
1188
+						goto skip_unlock;
1189
+				}else
1190
+					e->con.expire=now+S_TO_TICKS(sctp_options.sctp_autoclose);
1191
+				break;
1192
+			}
1193
+#if 0
1194
+			else if (TICKS_LT(e->con.expire, now)){
1195
+				WARN("sctp con: found expired assoc %d, id %d (%d s ago)\n",
1196
+						e->con.assoc_id, e->con.id,
1197
+						TICKS_TO_S(now-e->con.expire));
1198
+				if (_sctp_con_del_id_locked(h, e)==0)
1199
+					goto again; /* if unlocked need to restart the list */
1200
+			}
1201
+#endif
1202
+		}
1203
+	UNLOCK_SCTP_ID_H(h);
1204
+skip_unlock:
1205
+	return ret;
1206
+}
1207
+
1208
+
1209
+
1210
+/** using the assoc_id, remote addr. & socket, get the corresp. internal id.
1211
+ *  @param assoc_id - sctp assoc id
1212
+ *  @param si  - socket on which the packet was received
1213
+ *  @param del - if 1 delete the entry,
1214
+ *  @return assoc_id (!=0) on success, 0 on not found
1215
+ */
1216
+int sctp_con_get_id(unsigned int assoc_id, union sockaddr_union* remote,
1217
+					struct socket_info* si, int del)
1218
+{
1219
+	unsigned h;
1220
+	ticks_t now; 
1221
+	struct sctp_con_elem* e;
1222
+	struct sctp_con_elem* tmp;
1223
+	int ret;
1224
+	
1225
+	ret=0;
1226
+	now=get_ticks_raw();
1227
+	h=get_sctp_con_assoc_hash(assoc_id);
1228
+#if 0
1229
+again:
1230
+#endif
1231
+	LOCK_SCTP_ASSOC_H(h);
1232
+		clist_foreach_safe(&sctp_con_assoc_hash[h], e, tmp, l.next_assoc){
1233
+			if(e->con.assoc_id==assoc_id && e->con.si==si &&
1234
+					su_cmp(remote, &e->con.remote)){
1235
+				ret=e->con.id;
1236
+				if (del){
1237
+					if (_sctp_con_del_assoc_locked(h, e)==0)
1238
+						goto skip_unlock;
1239
+				}else
1240
+					e->con.expire=now+S_TO_TICKS(sctp_options.sctp_autoclose);
1241
+				break;
1242
+			}
1243
+#if 0
1244
+			else if (TICKS_LT(e->con.expire, now)){
1245
+				WARN("sctp con: found expired assoc %d, id %d (%d s ago)\n",
1246
+						e->con.assoc_id, e->con.id,
1247
+						TICKS_TO_S(now-e->con.expire));
1248
+				if (_sctp_con_del_assoc_locked(h, e)==0)
1249
+					goto again; /* if unlocked need to restart the list */
1250
+			}
1251
+#endif
1252
+		}
1253
+	UNLOCK_SCTP_ASSOC_H(h);
1254
+skip_unlock:
1255
+	return ret;
1256
+}
1257
+
1258
+
1259
+
1260
+#ifdef SCTP_ADDR_HASH
1261
+/** using the dest. & source socket, get the corresponding id and assoc_id 
1262
+ *  @param remote   - peer address & port
1263
+ *  @param si       - local source socket
1264
+ *  @param assoc_id - result, filled with the sctp assoc_id
1265
+ *  @param del - if 1 delete the entry,
1266
+ *  @return ser id (!=0) on success, 0 on not found
1267
+ */
1268
+int sctp_con_addr_get_id_assoc(union sockaddr_union* remote,
1269
+								struct socket_info* si,
1270
+								int* assoc_id, int del)
1271
+{
1272
+	unsigned h;
1273
+	ticks_t now; 
1274
+	struct sctp_con_elem* e;
1275
+	struct sctp_con_elem* tmp;
1276
+	int ret;
1277
+	
1278
+	ret=0;
1279
+	*assoc_id=0;
1280
+	now=get_ticks_raw();
1281
+	h=get_sctp_con_addr_hash(remote, si);
1282
+again:
1283
+	LOCK_SCTP_ADDR_H(h);
1284
+		clist_foreach_safe(&sctp_con_addr_hash[h], e, tmp, l.next_addr){
1285
+			if(su_cmp(remote, &e->con.remote) && e->con.si==si){
1286
+				ret=e->con.id;
1287
+				*assoc_id=e->con.assoc_id;
1288
+				if (del){
1289
+					if (_sctp_con_del_addr_locked(h, e)==0)
1290
+						goto skip_unlock;
1291
+				}else
1292
+					e->con.expire=now+S_TO_TICKS(sctp_options.sctp_autoclose);
1293
+				break;
1294
+			}
1295
+#if 0
1296
+			else if (TICKS_LT(e->con.expire, now)){
1297
+				WARN("sctp con: found expired assoc %d, id %d (%d s ago)\n",
1298
+						e->con.assoc_id, e->con.id,
1299
+						TICKS_TO_S(now-e->con.expire));
1300
+				if (_sctp_con_del_addr_locked(h, e)==0)
1301
+					goto again; /* if unlocked need to restart the list */
1302
+			}
1303
+#endif
1304
+		}
1305
+	UNLOCK_SCTP_ADDR_H(h);
1306
+skip_unlock:
1307
+	return ret;
1308
+}
1309
+#endif /* SCTP_ADDR_HASH */
1310
+
1311
+
1312
+
1313
+/** del con tracking for (assod_id, si).
1314
+ * @return 0 on success, -1 on error (not found)
1315
+ */
1316
+#define sctp_con_del_assoc(assoc_id, si) \
1317
+	(-(sctp_con_get_id((assoc_id), (si), 1)==0))
1318
+
1319
+
1320
+
1321
+/** create a new sctp con elem.
1322
+  * @param id - ser connection id
1323
+  * @param assoc_id - sctp assoc id
1324
+  * @param si - corresp. socket
1325
+  * @param remote - remote side
1326
+  * @return pointer to shm allocated sctp_con_elem on success, 0 on error
1327
+  */
1328
+struct sctp_con_elem* sctp_con_new(unsigned id, unsigned assoc_id, 
1329
+									struct socket_info* si,
1330
+									union sockaddr_union* remote)
1331
+{
1332
+	struct sctp_con_elem* e;
1333
+	
1334
+	e=shm_malloc(sizeof(*e));
1335
+	if (unlikely(e==0))
1336
+		goto error;
1337
+	e->l.next_id=e->l.prev_id=0;
1338
+	e->l.next_assoc=e->l.prev_assoc=0;
1339
+	atomic_set(&e->refcnt, 0);
1340
+	e->con.id=id;
1341
+	e->con.assoc_id=assoc_id;
1342
+	e->con.si=si;
1343
+	e->con.flags=0;
1344
+	if (likely(remote))
1345
+		e->con.remote=*remote;
1346
+	else
1347
+		memset(&e->con.remote, 0, sizeof(e->con.remote));
1348
+	e->con.start=get_ticks_raw();
1349
+	e->con.expire=e->con.start+S_TO_TICKS(sctp_options.sctp_autoclose);
1350
+	return e;
1351
+error:
1352
+	return 0;
1353
+}
1354
+
1355
+
1356
+
1357
+/** handles every ev on sctp assoc_id.
1358
+  * @return ser id on success (!=0) or 0 on not found/error
1359
+  */
1360
+static int sctp_con_track(int assoc_id, struct socket_info* si,
1361
+							union sockaddr_union* remote, int ev)
1362
+{
1363
+	int id;
1364
+	unsigned hash;
1365
+	unsigned assoc_hash;
1366
+	struct sctp_con_elem* e;
1367
+	struct sctp_con_elem* tmp;
1368
+	
1369
+	id=0;
1370
+	DBG("sctp_con_track(%d, %p, %d) \n", assoc_id, si, ev);
1371
+	
1372
+	/* search for (assoc_id, si) */
1373
+	assoc_hash=get_sctp_con_assoc_hash(assoc_id);
1374
+	LOCK_SCTP_ASSOC_H(assoc_hash);
1375
+		clist_foreach_safe(&sctp_con_assoc_hash[assoc_hash], e, tmp,
1376
+								l.next_assoc){
1377
+			/* we need to use the remote side address, because at least
1378
+			   on linux assoc_id are immediately reused (even if sctp
1379
+			   autoclose is off) and so it's possible that the association
1380
+			   id we saved is already closed and assigned to another
1381
+			   association by the time we search for it) */
1382
+			if(e->con.assoc_id==assoc_id && e->con.si==si &&
1383
+					su_cmp(remote, &e->con.remote)){
1384
+				if (ev==SCTP_CON_DOWN_SEEN){
1385
+					if (e->con.flags & SCTP_CON_UP_SEEN){
1386
+						/* DOWN after UP => delete */
1387
+						id=e->con.id;
1388
+						/* do delete */
1389
+						if (_sctp_con_del_assoc_locked(assoc_hash, e)==0)
1390
+							goto found; /* skip unlock */
1391
+					}else{
1392
+						/* DOWN after DOWN => error
1393
+						   DOWN after RCV w/ no UP -> not possible
1394
+						    since we never create a tracking entry on RCV
1395
+							only */
1396
+						BUG("unexpected flags: %x for assoc_id %d, id %d"
1397
+								", sctp con %p\n", e->con.flags, assoc_id,
1398
+								e->con.id, e);
1399
+						/* do delete */
1400
+						if (_sctp_con_del_assoc_locked(assoc_hash, e)==0)
1401
+							goto found; /* skip unlock */
1402
+					}
1403