Browse code

Merge commit 'origin/ser_core_cvs'

* commit 'origin/ser_core_cvs': (22 commits)
sctp: sctp_max_assocs support from the script
sctp: core.sctp_options shows now also sctp_max_assocs
sctp: max_assocs options
sctp: sctp_assoc_tracking support from the script
sctp: core.sctp_options shows now also sctp_assoc_tracking
sctp: assoc_tracking option
sctp: SCTP_PEER_ADDR_PARAMS fix for older kernels
sctp: assoc_reuse option
core: cfg vars for the new sctp options
core: sctp_options rpc updated
sctp: more config variables
tcp: remove unused var. decls
dns: fix missing out-of-memory check
- @next_hop.src_ip: source ip of outgoing message
sctp: retransmission options
sctp: sctp autoclose can now be changed at runtime
sctp: enable runtime changing for some of the cfg vars
tcp: minor fix: TCP_EV_IDLE_CONN_CLOSED
tcp: minor fix: TCP_EV_CONNECT_RST() not always called
sctp: compatibility with older linux kernels
...

Andrei Pelinescu-Onciul authored on 26/06/2009 18:25:09
Showing 15 changed files
... ...
@@ -338,9 +338,14 @@ new config variables:
338 338
   sctp_socket_rcvbuf = number - size for the sctp socket receive buffer
339 339
   sctp_socket_sndbuf = number - size for the sctp socket send buffer
340 340
   sctp_autoclose = seconds - number of seconds before autoclosing an idle
341
-     assocation (default: 180 s).
341
+                   association (default: 180 s).
342
+                   Can be changed at runtime, but it will affect only new
343
+                   associations. E.g.:
344
+                   $ sercmd cfg.set_now_int sctp autoclose 120
342 345
   sctp_send_ttl = milliseconds - number of milliseconds before an unsent
343
-     message/chunk is dropped (default: 32000 ms or 32 s).
346
+                  message/chunk is dropped (default: 32000 ms or 32 s).
347
+                  Can be changed at runtime, e.g.:
348
+                  $ sercmd cfg.set_now_int sctp send_ttl 180000
344 349
   sctp_send_retries - how many times to attempt re-sending a message on a
345 350
                       re-opened association, if the sctp stack did give up
346 351
                       sending it (it's not related to sctp protocol level
... ...
@@ -349,6 +354,105 @@ new config variables:
349 349
                       machine. WARNING: use with care and low values (e.g.
350 350
                       1-3) to avoid "multiplying" traffic to unresponding 
351 351
                       hosts (default: 0).
352
+                      Can be changed at runtime.
353
+  sctp_assoc_tracking = yes/no - controls whether or not sctp associations
354
+     are tracked inside ser/sip-router. Turning it off would result in
355
+     less memory being used and slightly better performance, but it will also
356
+     disable some other features that depend on it (e.g. sctp_assoc_reuse).
357
+     Default: yes.
358
+     Can be changed at runtime (sercmd sctp assoc_tracking 0), but changes
359
+     will be allowed only if all the other features that depend on it are
360
+     turned off (for example it can be turned off only if first
361
+     sctp_assoc_reuse was turned off).
362
+     Note: turning sctp_assoc_tracking on/off will delete all the tracking
363
+     information for all the currently tracked associations and might introduce
364
+     a small temporary delay in the sctp processing if lots of associations
365
+     were tracked.
366
+     Config options depending on sctp_assoc_tracking being on:
367
+      sctp_assoc_reuse.
368
+  sctp_assoc_reuse = yes/no - controls sctp association reuse. For now only
369
+     association reuse for replies is affected by it. Default: yes.
370
+     Depends on sctp_assoc_tracking being on.
371
+     Note that even if turned off, if the port in via corresponds to the
372
+     source port of the association the request was sent on or if rport is
373
+     turned on (force_rport() or via containing a rport option), the
374
+     association will be automatically reused by the sctp stack.
375
+     Can be changed at runtime (sctp assoc_reuse), but it can be turned on
376
+     only if sctp_assoc_tracking is on.
377
+  sctp_max_assocs = number - maximum number of allowed open sctp associations.
378
+     -1 means maximum allowed by the OS. Default: -1.
379
+     Can be changed at runtime (e.g.:
380
+      sercmd cfg.set_now_int sctp max_assocs 10 ).
381
+     When the maximum associations number is exceeded and a new associations
382
+     is opened by a remote host, the association will be immediately closed.
383
+     However it is possible that some sip packets get through (especially if
384
+     they are sent early, as part of the 4-way handshake).
385
+     When ser/sip-router tries to open a new association and the max_assocs
386
+     is exceeded the exact behaviour depends on whether or not
387
+     sctp_assoc_tracking is on. If on, the send triggering the active open
388
+     will gracefully fail, before actually opening the new association and no
389
+     packet will be sent. However if sctp_assoc_tracking is off, the
390
+     association will first be opened and then immediately closed. In general
391
+     this means that the initial sip packet will be sent (as part of the 4-way
392
+     handshake).
393
+  sctp_srto_initial = milliseconds - initial value of the retr. timeout, used
394
+     in RTO calculations (default: OS specific).
395
+     Can be changed at runtime (sctp srto_initial) but it will affect only new
396
+     associations.
397
+  sctp_srto_max = milliseconds - maximum value of the retransmission timeout
398
+     (RTO) (default: OS specific).
399
+     WARNING: values lower then the sctp sack_delay will cause lots of
400
+     retransmissions and connection instability (see sctp_srto_min for more
401
+     details).
402
+     Can be changed at runtime (sctp srto_max) but it will affect only new
403
+     associations.
404
+  sctp_srto_min = milliseconds - minimum value of the retransmission timeout
405
+     (RTO) (default: OS specific).
406
+     WARNING: values lower then the sctp sack_delay of any peer might cause
407
+     retransmissions and possible interoperability problems. According to the
408
+     standard the sack_delay should be between 200 and 500 ms, so avoid trying
409
+     values lower then 500 ms unless you control all the possible sctp peers
410
+     and you do make sure their sack_delay is higher or their sack_freq is 1.
411
+     Can be changed at runtime (sctp srto_min) but it will affect only new
412
+     associations.
413
+  sctp_asocmaxrxt   = number - maximum retransmissions attempts per association
414
+     (default: OS specific). It should be set to sctp_pathmaxrxt * no. of
415
+     expected paths.
416
+     Can be changed at runtime (sctp asocmaxrxt) but it will affect only new
417
+     associations.
418
+  sctp_init_max_attempts = number - maximum INIT retransmission attempts
419
+     (default: OS specific).
420
+     Can be changed at runtime (sctp init_max_attempts).
421
+  sctp_init_max_timeo = milliseconds - maximum INIT retransmission timeout (RTO
422
+     max for INIT). Default: OS specific.
423
+     Can be changed at runtime (sctp init_max_timeo).
424
+  sctp_hbinterval = milliseconds - sctp heartbeat interval. Setting it to -1
425
+     will disable the heartbeats. Default: OS specific.
426
+     Can be changed at runtime (sctp hbinterval) but it will affect only new
427
+     associations.
428
+  sctp_pathmaxrxt = number - maximum retransmission attempts per path (see also
429
+     sctp_asocmaxrxt). Default: OS specific.
430
+     Can be changed at runtime (sctp pathmaxrxt) but it will affect only new
431
+     associations.
432
+  sctp_sack_delay = milliseconds - delay until an ACK is generated after
433
+     receiving a packet. Default: OS specific.
434
+     WARNING: a value higher then srto_min can cause a lot of retransmissions
435
+     (and strange problems). A value higher then srto_max will result in very
436
+     high connections instability. According to the standard the sack_delay
437
+     value should be between 200 and 500 ms.
438
+     Can be changed at runtime (sctp sack_delay) but it will affect only new
439
+     associations.
440
+  sctp_sack_freq = number - number of packets received before an ACK is sent
441
+     (without waiting for the sack_delay to expire).  Default: OS specific.
442
+     Note: on linux with lksctp up to and including 1.0.9 is not possible to
443
+     set this value (having it in the config will produce a warning on
444
+     startup).
445
+     Can be changed at runtime (sctp sack_freq) but it will affect only new
446
+     associations.
447
+  sctp_max_burst = number - maximum burst of packets that can be emitted by an
448
+     association. Default: OS specific.
449
+     Can be changed at runtime (sctp max_burst) but it will affect only new 
450
+     associations.
352 451
   server_id = number - A configurable unique server id that can be used to
353 452
                        discriminate server instances within a cluster of
354 453
                        servers when all other information, such as IP addresses
... ...
@@ -378,6 +378,21 @@ SCTP_SOCKET_SNDBUF	"sctp_socket_sndbuf"|"sctp_socket_send_buffer"
378 378
 SCTP_AUTOCLOSE	"sctp_autoclose"
379 379
 SCTP_SEND_TTL	"sctp_send_ttl"
380 380
 SCTP_SEND_RETRIES	"sctp_send_retries"
381
+SCTP_ASSOC_TRACKING	"sctp_assoc_tracking"
382
+SCTP_ASSOC_REUSE	"sctp_assoc_reuse"
383
+SCTP_MAX_ASSOCS		"sctp_max_assocs"
384
+SCTP_SRTO_INITIAL	"sctp_srto_initial"
385
+SCTP_SRTO_MAX		"sctp_srto_max"
386
+SCTP_SRTO_MIN		"sctp_srto_min"
387
+SCTP_ASOCMAXRXT		"sctp_asocmaxrxt"
388
+SCTP_INIT_MAX_ATTEMPTS		"sctp_init_max_attempts"
389
+SCTP_INIT_MAX_TIMEO			"sctp_init_max_timeo"
390
+SCTP_HBINTERVAL				"sctp_hbinterval"
391
+SCTP_PATHMAXRXT				"sctp_pathmaxrxt"
392
+SCTP_SACK_DELAY				"sctp_sack_delay"
393
+SCTP_SACK_FREQ				"sctp_sack_freq"
394
+SCTP_MAX_BURST				"sctp_max_burst"
395
+
381 396
 ADVERTISED_ADDRESS	"advertised_address"
382 397
 ADVERTISED_PORT		"advertised_port"
383 398
 DISABLE_CORE		"disable_core_dump"
... ...
@@ -715,6 +730,34 @@ EAT_ABLE	[\ \t\b\r]
715 715
 										return SCTP_SEND_TTL; }
716 716
 <INITIAL>{SCTP_SEND_RETRIES}	{ count(); yylval.strval=yytext;
717 717
 										return SCTP_SEND_RETRIES; }
718
+<INITIAL>{SCTP_ASSOC_TRACKING}	{ count(); yylval.strval=yytext;
719
+										return SCTP_ASSOC_TRACKING; }
720
+<INITIAL>{SCTP_ASSOC_REUSE}		{ count(); yylval.strval=yytext;
721
+										return SCTP_ASSOC_REUSE; }
722
+<INITIAL>{SCTP_MAX_ASSOCS}		{ count(); yylval.strval=yytext;
723
+										return SCTP_MAX_ASSOCS; }
724
+<INITIAL>{SCTP_SRTO_INITIAL}	{ count(); yylval.strval=yytext;
725
+										return SCTP_SRTO_INITIAL; }
726
+<INITIAL>{SCTP_SRTO_MAX}	{ count(); yylval.strval=yytext;
727
+										return SCTP_SRTO_MAX; }
728
+<INITIAL>{SCTP_SRTO_MIN}	{ count(); yylval.strval=yytext;
729
+										return SCTP_SRTO_MIN; }
730
+<INITIAL>{SCTP_ASOCMAXRXT}	{ count(); yylval.strval=yytext;
731
+										return SCTP_ASOCMAXRXT; }
732
+<INITIAL>{SCTP_INIT_MAX_ATTEMPTS}	{ count(); yylval.strval=yytext;
733
+										return SCTP_INIT_MAX_ATTEMPTS; }
734
+<INITIAL>{SCTP_INIT_MAX_TIMEO}	{ count(); yylval.strval=yytext;
735
+										return SCTP_INIT_MAX_TIMEO; }
736
+<INITIAL>{SCTP_HBINTERVAL}	{ count(); yylval.strval=yytext;
737
+										return SCTP_HBINTERVAL; }
738
+<INITIAL>{SCTP_PATHMAXRXT}	{ count(); yylval.strval=yytext;
739
+										return SCTP_PATHMAXRXT; }
740
+<INITIAL>{SCTP_SACK_DELAY}	{ count(); yylval.strval=yytext;
741
+										return SCTP_SACK_DELAY; }
742
+<INITIAL>{SCTP_SACK_FREQ}	{ count(); yylval.strval=yytext;
743
+										return SCTP_SACK_FREQ; }
744
+<INITIAL>{SCTP_MAX_BURST}	{ count(); yylval.strval=yytext;
745
+										return SCTP_MAX_BURST; }
718 746
 <INITIAL>{SERVER_SIGNATURE}	{ count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
719 747
 <INITIAL>{REPLY_TO_VIA}	{ count(); yylval.strval=yytext; return REPLY_TO_VIA; }
720 748
 <INITIAL>{ADVERTISED_ADDRESS}	{	count(); yylval.strval=yytext;
... ...
@@ -185,6 +185,12 @@
185 185
 	#define IF_STUN(x) warn("stun support not compiled in")
186 186
 #endif
187 187
 
188
+#ifdef USE_SCTP
189
+	#define IF_SCTP(x) x
190
+#else
191
+	#define IF_SCTP(x) warn("sctp support not compiled in")
192
+#endif
193
+
188 194
 
189 195
 extern int yylex();
190 196
 static void yyerror(char* s, ...);
... ...
@@ -439,6 +445,20 @@ static int case_check_default(struct case_stms* stms);
439 439
 %token SCTP_AUTOCLOSE
440 440
 %token SCTP_SEND_TTL
441 441
 %token SCTP_SEND_RETRIES
442
+%token SCTP_ASSOC_TRACKING
443
+%token SCTP_ASSOC_REUSE
444
+%token SCTP_MAX_ASSOCS
445
+%token SCTP_SRTO_INITIAL
446
+%token SCTP_SRTO_MAX
447
+%token SCTP_SRTO_MIN
448
+%token SCTP_ASOCMAXRXT
449
+%token SCTP_INIT_MAX_ATTEMPTS
450
+%token SCTP_INIT_MAX_TIMEO
451
+%token SCTP_HBINTERVAL
452
+%token SCTP_PATHMAXRXT
453
+%token SCTP_SACK_DELAY
454
+%token SCTP_SACK_FREQ
455
+%token SCTP_MAX_BURST
442 456
 %token ADVERTISED_ADDRESS
443 457
 %token ADVERTISED_PORT
444 458
 %token DISABLE_CORE
... ...
@@ -1214,7 +1234,7 @@ assign_stm:
1214 1214
 	| SCTP_CHILDREN EQUAL error { yyerror("number expected"); }
1215 1215
 	| SCTP_SOCKET_RCVBUF EQUAL NUMBER {
1216 1216
 		#ifdef USE_SCTP
1217
-			sctp_options.sctp_so_rcvbuf=$3;
1217
+			sctp_default_cfg.so_rcvbuf=$3;
1218 1218
 		#else
1219 1219
 			warn("sctp support not compiled in");
1220 1220
 		#endif
... ...
@@ -1222,7 +1242,7 @@ assign_stm:
1222 1222
 	| SCTP_SOCKET_RCVBUF EQUAL error { yyerror("number expected"); }
1223 1223
 	| SCTP_SOCKET_SNDBUF EQUAL NUMBER {
1224 1224
 		#ifdef USE_SCTP
1225
-			sctp_options.sctp_so_sndbuf=$3;
1225
+			sctp_default_cfg.so_sndbuf=$3;
1226 1226
 		#else
1227 1227
 			warn("sctp support not compiled in");
1228 1228
 		#endif
... ...
@@ -1230,7 +1250,7 @@ assign_stm:
1230 1230
 	| SCTP_SOCKET_SNDBUF EQUAL error { yyerror("number expected"); }
1231 1231
 	| SCTP_AUTOCLOSE EQUAL NUMBER {
1232 1232
 		#ifdef USE_SCTP
1233
-			sctp_options.sctp_autoclose=$3;
1233
+			sctp_default_cfg.autoclose=$3;
1234 1234
 		#else
1235 1235
 			warn("sctp support not compiled in");
1236 1236
 		#endif
... ...
@@ -1238,7 +1258,7 @@ assign_stm:
1238 1238
 	| SCTP_AUTOCLOSE EQUAL error { yyerror("number expected"); }
1239 1239
 	| SCTP_SEND_TTL EQUAL NUMBER {
1240 1240
 		#ifdef USE_SCTP
1241
-			sctp_options.sctp_send_ttl=$3;
1241
+			sctp_default_cfg.send_ttl=$3;
1242 1242
 		#else
1243 1243
 			warn("sctp support not compiled in");
1244 1244
 		#endif
... ...
@@ -1246,12 +1266,88 @@ assign_stm:
1246 1246
 	| SCTP_SEND_TTL EQUAL error { yyerror("number expected"); }
1247 1247
 	| SCTP_SEND_RETRIES EQUAL NUMBER {
1248 1248
 		#ifdef USE_SCTP
1249
-			sctp_options.sctp_send_retries=$3;
1249
+			sctp_default_cfg.send_retries=$3;
1250 1250
 		#else
1251 1251
 			warn("sctp support not compiled in");
1252 1252
 		#endif
1253 1253
 	}
1254 1254
 	| SCTP_SEND_RETRIES EQUAL error { yyerror("number expected"); }
1255
+	| SCTP_ASSOC_TRACKING EQUAL NUMBER {
1256
+		#ifdef USE_SCTP
1257
+			#ifdef SCTP_CONN_REUSE
1258
+				sctp_default_cfg.assoc_tracking=$3;
1259
+			#else
1260
+				if ($3)
1261
+					warn("sctp association tracking/reuse (SCTP_CONN_REUSE) "
1262
+							"support not compiled in");
1263
+			#endif /* SCTP_CONN_REUSE */
1264
+		#else
1265
+			warn("sctp support not compiled in");
1266
+		#endif /* USE_SCTP */
1267
+	}
1268
+	| SCTP_ASSOC_TRACKING EQUAL error { yyerror("number expected"); }
1269
+	| SCTP_ASSOC_REUSE EQUAL NUMBER {
1270
+		#ifdef USE_SCTP
1271
+			#ifdef SCTP_CONN_REUSE
1272
+				sctp_default_cfg.assoc_reuse=$3;
1273
+			#else
1274
+				if ($3)
1275
+					warn("sctp association reuse (SCTP_CONN_REUSE) support"
1276
+							" not compiled in");
1277
+			#endif /* SCTP_CONN_REUSE */
1278
+		#else
1279
+			warn("sctp support not compiled in");
1280
+		#endif /* USE_SCTP */
1281
+	}
1282
+	| SCTP_ASSOC_REUSE EQUAL error { yyerror("number expected"); }
1283
+	| SCTP_MAX_ASSOCS EQUAL NUMBER {
1284
+			IF_SCTP(sctp_default_cfg.max_assocs=$3);
1285
+	}
1286
+	| SCTP_MAX_ASSOCS EQUAL error { yyerror("number expected"); }
1287
+	| SCTP_SRTO_INITIAL EQUAL NUMBER {
1288
+			IF_SCTP(sctp_default_cfg.srto_initial=$3);
1289
+	}
1290
+	| SCTP_SRTO_INITIAL EQUAL error { yyerror("number expected"); }
1291
+	| SCTP_SRTO_MAX EQUAL NUMBER {
1292
+			IF_SCTP(sctp_default_cfg.srto_max=$3);
1293
+	}
1294
+	| SCTP_SRTO_MAX EQUAL error { yyerror("number expected"); }
1295
+	| SCTP_SRTO_MIN EQUAL NUMBER {
1296
+			IF_SCTP(sctp_default_cfg.srto_min=$3);
1297
+	}
1298
+	| SCTP_SRTO_MIN EQUAL error { yyerror("number expected"); }
1299
+	| SCTP_ASOCMAXRXT EQUAL NUMBER {
1300
+			IF_SCTP(sctp_default_cfg.asocmaxrxt=$3);
1301
+	}
1302
+	| SCTP_ASOCMAXRXT EQUAL error { yyerror("number expected"); }
1303
+	| SCTP_INIT_MAX_ATTEMPTS EQUAL NUMBER {
1304
+			IF_SCTP(sctp_default_cfg.init_max_attempts=$3);
1305
+	}
1306
+	| SCTP_INIT_MAX_ATTEMPTS EQUAL error { yyerror("number expected"); }
1307
+	| SCTP_INIT_MAX_TIMEO EQUAL NUMBER {
1308
+			IF_SCTP(sctp_default_cfg.init_max_timeo=$3);
1309
+	}
1310
+	| SCTP_INIT_MAX_TIMEO EQUAL error { yyerror("number expected"); }
1311
+	| SCTP_HBINTERVAL EQUAL NUMBER {
1312
+			IF_SCTP(sctp_default_cfg.hbinterval=$3);
1313
+	}
1314
+	| SCTP_HBINTERVAL EQUAL error { yyerror("number expected"); }
1315
+	| SCTP_PATHMAXRXT EQUAL NUMBER {
1316
+			IF_SCTP(sctp_default_cfg.pathmaxrxt=$3);
1317
+	}
1318
+	| SCTP_PATHMAXRXT EQUAL error { yyerror("number expected"); }
1319
+	| SCTP_SACK_DELAY EQUAL NUMBER {
1320
+			IF_SCTP(sctp_default_cfg.sack_delay=$3);
1321
+	}
1322
+	| SCTP_SACK_DELAY EQUAL error { yyerror("number expected"); }
1323
+	| SCTP_SACK_FREQ EQUAL NUMBER {
1324
+			IF_SCTP(sctp_default_cfg.sack_freq=$3);
1325
+	}
1326
+	| SCTP_SACK_FREQ EQUAL error { yyerror("number expected"); }
1327
+	| SCTP_MAX_BURST EQUAL NUMBER {
1328
+			IF_SCTP(sctp_default_cfg.max_burst=$3);
1329
+	}
1330
+	| SCTP_MAX_BURST EQUAL error { yyerror("number expected"); }
1255 1331
 	| SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
1256 1332
 	| SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
1257 1333
 	| REPLY_TO_VIA EQUAL NUMBER { reply_to_via=$3; }
... ...
@@ -627,16 +627,31 @@ static void core_sctp_options(rpc_t* rpc, void* c)
627 627
 {
628 628
 #ifdef USE_SCTP
629 629
 	void *handle;
630
-	struct sctp_cfg_options t;
630
+	struct cfg_group_sctp t;
631 631
 
632 632
 	if (!sctp_disable){
633 633
 		sctp_options_get(&t);
634 634
 		rpc->add(c, "{", &handle);
635
-		rpc->struct_add(handle, "dddd",
636
-			"sctp_autoclose",		t.sctp_autoclose,
637
-			"sctp_send_ttl",	t.sctp_autoclose,
638
-			"sctp_socket_rcvbuf",	t.sctp_so_rcvbuf,
639
-			"sctp_socket_sndbuf",	t.sctp_so_sndbuf
635
+		rpc->struct_add(handle, "ddddddddddddddddddd",
636
+			"sctp_socket_rcvbuf",	t.so_rcvbuf,
637
+			"sctp_socket_sndbuf",	t.so_sndbuf,
638
+			"sctp_autoclose",		t.autoclose,
639
+			"sctp_send_ttl",	t.send_ttl,
640
+			"sctp_send_retries",	t.send_retries,
641
+			"sctp_assoc_tracking",	t.assoc_tracking,
642
+			"sctp_assoc_reuse",	t.assoc_reuse,
643
+			"sctp_max_assocs", t.max_assocs,
644
+			"sctp_srto_initial",	t.srto_initial,
645
+			"sctp_srto_max",		t.srto_max,
646
+			"sctp_srto_min",		t.srto_min,
647
+			"sctp_asocmaxrxt",	t.asocmaxrxt,
648
+			"sctp_init_max_attempts",	t.init_max_attempts,
649
+			"sctp_init_max_timeo",t.init_max_timeo,
650
+			"sctp_hbinterval",	t.hbinterval,
651
+			"sctp_pathmaxrxt",	t.pathmaxrxt,
652
+			"sctp_sack_delay",	t.sack_delay,
653
+			"sctp_sack_freq",	t.sack_freq,
654
+			"sctp_max_burst",	t.max_burst
640 655
 		);
641 656
 	}else{
642 657
 		rpc->fault(c, 500, "sctp support disabled");
... ...
@@ -1866,7 +1866,7 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1866 1866
 	if (type==T_A){
1867 1867
 		if ((ip=str2ip(name))!=0){
1868 1868
 				e=dns_cache_mk_ip_entry(name, ip);
1869
-				if (e)
1869
+				if (likely(e))
1870 1870
 					atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1871 1871
 				goto end; /* we do not cache obvious stuff */
1872 1872
 		}
... ...
@@ -1875,7 +1875,7 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1875 1875
 	else if (type==T_AAAA){
1876 1876
 		if ((ip=str2ip6(name))!=0){
1877 1877
 				e=dns_cache_mk_ip_entry(name, ip);
1878
-				if (e)
1878
+				if (likely(e))
1879 1879
 					atomic_set(&e->refcnt, 1);/* because we ret. a ref. to it*/
1880 1880
 				goto end;/* we do not cache obvious stuff */
1881 1881
 		}
... ...
@@ -1897,12 +1897,12 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1897 1897
 	if (records){
1898 1898
 #ifdef CACHE_RELEVANT_RECS_ONLY
1899 1899
 		e=dns_cache_mk_rd_entry(name, type, &records);
1900
-		if (e){
1900
+		if (likely(e)){
1901 1901
 			l=e;
1902 1902
 			e=dns_get_related(l, type, &records);
1903 1903
 			/* e should contain the searched entry (if found) and l
1904 1904
 			 * all the entries (e and related) */
1905
-			if (e){
1905
+			if (likely(e)){
1906 1906
 				atomic_set(&e->refcnt, 1); /* 1 because we return a
1907 1907
 												ref. to it */
1908 1908
 			}else{
... ...
@@ -1943,9 +1943,12 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
1943 1943
 #endif
1944 1944
 		free_rdata_list(records);
1945 1945
 	}else if (cfg_get(core, core_cfg, dns_neg_cache_ttl)){
1946
-		e=dns_cache_mk_bad_entry(name, type, cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_BAD_NAME);
1947
-		atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
1948
-		dns_cache_add(e); /* refcnt++ inside*/
1946
+		e=dns_cache_mk_bad_entry(name, type, 
1947
+				cfg_get(core, core_cfg, dns_neg_cache_ttl), DNS_BAD_NAME);
1948
+		if (likely(e)) {
1949
+			atomic_set(&e->refcnt, 1); /* 1 because we return a ref. to it */
1950
+			dns_cache_add(e); /* refcnt++ inside*/
1951
+		}
1949 1952
 		goto end;
1950 1953
 	}
1951 1954
 #ifndef CACHE_RELEVANT_RECS_ONLY
... ...
@@ -1960,6 +1960,12 @@ try_again:
1960 1960
 		goto error;
1961 1961
 	}
1962 1962
 #endif /* USE_TCP */
1963
+#ifdef USE_SCTP
1964
+	if (sctp_register_cfg()){
1965
+		LOG(L_CRIT, "could not register the sctp configuration\n");
1966
+		goto error;
1967
+	}
1968
+#endif /* USE_SCTP */
1963 1969
 	/*init timer, before parsing the cfg!*/
1964 1970
 	if (init_timer()<0){
1965 1971
 		LOG(L_CRIT, "could not initialize timer, exiting...\n");
... ...
@@ -22,31 +22,132 @@
22 22
  * History:
23 23
  * --------
24 24
  *  2008-08-07  initial version (andrei)
25
+ *  2009-05-26  runtime cfg support (andrei)
25 26
  */
26 27
 
28
+#include <string.h>
29
+#include <sys/types.h>
30
+#include <sys/socket.h>
31
+#include <netinet/in.h>
32
+#include <netinet/in_systm.h>
33
+#include <netinet/ip.h>
34
+#include <netinet/sctp.h>
35
+#include <errno.h>
27 36
 
28 37
 #include "sctp_options.h"
29 38
 #include "dprint.h"
39
+#include "cfg/cfg.h"
40
+#include "socket_info.h"
41
+#include "sctp_server.h"
30 42
 
43
+struct cfg_group_sctp sctp_default_cfg;
31 44
 
32
-struct sctp_cfg_options sctp_options;
45
+
46
+
47
+#ifdef USE_SCTP
48
+
49
+
50
+static int set_autoclose(void* cfg_h, str* gname, str* name, void** val);
51
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val);
52
+static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val);
53
+static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val);
54
+static int set_srto_max(void* cfg_h, str* gname, str* name, void** val);
55
+static int set_srto_min(void* cfg_h, str* gname, str* name, void** val);
56
+static int set_asocmaxrxt(void* cfg_h, str* gname, str* name, void** val);
57
+static int set_sinit_max_attempts(void* cfg_h, str* gname, str* name,
58
+										void** val);
59
+static int set_sinit_max_init_timeo(void* cfg_h, str* gname, str* name,
60
+										void** val);
61
+static int set_hbinterval(void* cfg_h, str* gname, str* name, void** val);
62
+static int set_pathmaxrxt(void* cfg_h, str* gname, str* name, void** val);
63
+static int set_sack_freq(void* cfg_h, str* gname, str* name, void** val);
64
+static int set_sack_delay(void* cfg_h, str* gname, str* name, void** val);
65
+static int set_max_burst(void* cfg_h, str* gname, str* name, void** val);
66
+
67
+/** cfg_group_sctp description (for the config framework). */
68
+static cfg_def_t sctp_cfg_def[] = {
69
+	/*   name        , type |input type| chg type, min, max, fixup, proc. cbk.
70
+	      description */
71
+	{ "socket_rcvbuf", CFG_VAR_INT| CFG_READONLY, 512, 102400, 0, 0,
72
+		"socket receive buffer size (read-only)" },
73
+	{ "socket_sndbuf", CFG_VAR_INT| CFG_READONLY, 512, 102400, 0, 0,
74
+		"socket send buffer size (read-only)" },
75
+	{ "autoclose", CFG_VAR_INT| CFG_ATOMIC, 1, 1<<30, set_autoclose, 0,
76
+		"seconds before closing and idle connection (must be non-zero)" },
77
+	{ "send_ttl", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, 0, 0,
78
+		"milliseconds before aborting a send" },
79
+	{ "send_retries", CFG_VAR_INT| CFG_ATOMIC, 0, MAX_SCTP_SEND_RETRIES, 0, 0,
80
+		"re-send attempts on failure" },
81
+	{ "assoc_tracking", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_tracking, 0,
82
+		"connection/association tracking (see also assoc_reuse)" },
83
+	{ "assoc_reuse", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_reuse, 0,
84
+		"connection/association reuse (for now used only for replies)"
85
+		", depends on assoc_tracking being set"},
86
+	{ "max_assocs", CFG_VAR_INT| CFG_ATOMIC, 0, 0, 0, 0,
87
+		"maximum allowed open associations (-1 = disable, "
88
+			"as many as allowed by the OS)"},
89
+	{ "srto_initial", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_initial, 0,
90
+		"initial value of the retr. timeout, used in RTO calculations,"
91
+			" in msecs" },
92
+	{ "srto_max", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_max, 0,
93
+		"maximum value of the retransmission timeout (RTO), in msecs" },
94
+	{ "srto_min", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_min, 0,
95
+		"minimum value of the retransmission timeout (RTO), in msecs" },
96
+	{ "asocmaxrxt", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_asocmaxrxt, 0,
97
+		"maximum retransmission attempts per association" },
98
+	{ "init_max_attempts", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10,
99
+		set_sinit_max_attempts, 0, "max INIT retransmission attempts" },
100
+	{ "init_max_timeo", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10,
101
+		set_sinit_max_init_timeo, 0,
102
+		"max INIT retransmission timeout (RTO max for INIT), in msecs" },
103
+	{ "hbinterval", CFG_VAR_INT| CFG_ATOMIC, 0, 0, set_hbinterval, 0,
104
+		"heartbeat interval in msecs" },
105
+	{ "pathmaxrxt", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_pathmaxrxt, 0,
106
+		"maximum retransmission attempts per path" },
107
+	{ "sack_delay", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_sack_delay, 0,
108
+		"time since the last received packet before sending a SACK, in msecs"},
109
+	{ "sack_freq", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_sack_freq, 0,
110
+		"number of received packets that trigger the sending of a SACK"},
111
+	{ "max_burst", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_max_burst, 0,
112
+		"maximum burst of packets that can be emitted by an association"},
113
+	{0, 0, 0, 0, 0, 0, 0}
114
+};
115
+
116
+
117
+
118
+void* sctp_cfg; /* sctp config handle */
119
+
120
+#endif /* USE_SCTP */
33 121
 
34 122
 void init_sctp_options()
35 123
 {
36 124
 #ifdef USE_SCTP
37
-	sctp_options.sctp_autoclose=DEFAULT_SCTP_AUTOCLOSE; /* in seconds */
38
-	sctp_options.sctp_send_ttl=DEFAULT_SCTP_SEND_TTL;   /* in milliseconds */
39
-	sctp_options.sctp_send_retries=DEFAULT_SCTP_SEND_RETRIES;
125
+	sctp_get_os_defaults(&sctp_default_cfg);
126
+#if 0
127
+	sctp_default_cfg.so_rcvbuf=0; /* do nothing, use the kernel default */
128
+	sctp_default_cfg.so_sndbuf=0; /* do nothing, use the kernel default */
129
+#endif
130
+	sctp_default_cfg.autoclose=DEFAULT_SCTP_AUTOCLOSE; /* in seconds */
131
+	sctp_default_cfg.send_ttl=DEFAULT_SCTP_SEND_TTL;   /* in milliseconds */
132
+	sctp_default_cfg.send_retries=DEFAULT_SCTP_SEND_RETRIES;
133
+	sctp_default_cfg.max_assocs=-1; /* as much as possible by default */
134
+#ifdef SCTP_CONN_REUSE
135
+	sctp_default_cfg.assoc_tracking=1; /* on by default */
136
+	sctp_default_cfg.assoc_reuse=1; /* on by default */
137
+#else
138
+	sctp_default_cfg.assoc_tracking=0;
139
+	sctp_default_cfg.assoc_reuse=0;
140
+#endif /* SCTP_CONN_REUSE */
40 141
 #endif
41 142
 }
42 143
 
43 144
 
44 145
 
45 146
 #define W_OPT_NSCTP(option) \
46
-	if (sctp_options.option){\
147
+	if (sctp_default_cfg.option){\
47 148
 		WARN("sctp_options: " #option \
48 149
 			" cannot be enabled (sctp support not compiled-in)\n"); \
49
-			sctp_options.option=0; \
150
+			sctp_default_cfg.option=0; \
50 151
 	}
51 152
 
52 153
 
... ...
@@ -54,21 +155,425 @@ void init_sctp_options()
54 54
 void sctp_options_check()
55 55
 {
56 56
 #ifndef USE_SCTP
57
-	W_OPT_NSCTP(sctp_autoclose);
58
-	W_OPT_NSCTP(sctp_send_ttl);
59
-	W_OPT_NSCTP(sctp_send_retries);
60
-#else
61
-	if (sctp_options.sctp_send_retries>MAX_SCTP_SEND_RETRIES) {
57
+	W_OPT_NSCTP(autoclose);
58
+	W_OPT_NSCTP(send_ttl);
59
+	W_OPT_NSCTP(send_retries);
60
+	W_OPT_NSCTP(assoc_tracking);
61
+	W_OPT_NSCTP(assoc_reuse);
62
+	W_OPT_NSCTP(max_assocs);
63
+#else /* USE_SCTP */
64
+	if (sctp_default_cfg.send_retries>MAX_SCTP_SEND_RETRIES) {
62 65
 		WARN("sctp: sctp_send_retries too high (%d), setting it to %d\n",
63
-				sctp_options.sctp_send_retries, MAX_SCTP_SEND_RETRIES);
64
-		sctp_options.sctp_send_retries=MAX_SCTP_SEND_RETRIES;
66
+				sctp_default_cfg.send_retries, MAX_SCTP_SEND_RETRIES);
67
+		sctp_default_cfg.send_retries=MAX_SCTP_SEND_RETRIES;
65 68
 	}
66
-#endif
69
+#ifndef CONN_REUSE
70
+	if (sctp_default_cfg.assoc_tracking || sctp_default_cfg.assoc_reuse){
71
+		WARN("sctp_options: assoc_tracking and assoc_reuse support cannnot"
72
+				" be enabled (CONN_REUSE support not compiled-in)\n");
73
+		sctp_default_cfg.assoc_tracking=0;
74
+		sctp_default_cfg.assoc_reuse=0;
75
+	}
76
+#else /* CONN_REUSE */
77
+	if (sctp_default_cfg.assoc_reuse && sctp_default_cfg.assoc_tracking==0){
78
+		sctp_default_cfg.assoc_tracking=1;
79
+	}
80
+#endif /* CONN_REUSE */
81
+#endif /* USE_SCTP */
82
+}
83
+
84
+
85
+
86
+void sctp_options_get(struct cfg_group_sctp *s)
87
+{
88
+#ifdef USE_SCTP
89
+	*s=*(struct cfg_group_sctp*)sctp_cfg;
90
+#else
91
+	memset(s, 0, sizeof(*s));
92
+#endif /* USE_SCTP */
93
+}
94
+
95
+
96
+
97
+#ifdef USE_SCTP
98
+/** register sctp config into the configuration framework.
99
+ * @return 0 on success, -1 on error */
100
+int sctp_register_cfg()
101
+{
102
+	if (cfg_declare("sctp", sctp_cfg_def, &sctp_default_cfg, cfg_sizeof(sctp),
103
+				&sctp_cfg))
104
+		return -1;
105
+	if (sctp_cfg==0){
106
+		BUG("null sctp cfg");
107
+		return -1;
108
+	}
109
+	return 0;
110
+}
111
+
112
+
113
+
114
+#define SCTP_SET_SOCKOPT_DECLS \
115
+	int err; \
116
+	struct socket_info* si
117
+
118
+#define SCTP_SET_SOCKOPT_BODY(lev, opt_name, val, err_prefix) \
119
+	err=0; \
120
+	for (si=sctp_listen; si; si=si->next){ \
121
+		err+=(sctp_setsockopt(si->socket, (lev), (opt_name), (void*)(&(val)), \
122
+							sizeof((val)), (err_prefix))<0); \
123
+	} \
124
+	return -(err!=0)
125
+
126
+
127
+
128
+static int set_autoclose(void* cfg_h, str* gname, str* name, void** val)
129
+{
130
+#ifdef SCTP_AUTOCLOSE
131
+	int optval;
132
+	SCTP_SET_SOCKOPT_DECLS;
133
+	
134
+	optval=(int)(long)(*val);
135
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_AUTOCLOSE, optval,
136
+							"cfg: setting SCTP_AUTOCLOSE");
137
+#else
138
+	ERR("no SCTP_AUTOCLOSE support, please upgrade your sctp library\n");
139
+	return -1;
140
+#endif /* SCTP_AUTOCLOSE */
141
+}
142
+
143
+
144
+
145
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val)
146
+{
147
+	int optval;
148
+	
149
+	optval=(int)(long)(*val);
150
+#ifndef SCTP_CONN_REUSE
151
+	if (optval!=0){
152
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
153
+		return -1;
154
+	}
155
+#else /* SCTP_CONN_REUSE */
156
+	if (optval==0){
157
+		/* turn tracking off */
158
+		/* check if assoc_reuse is off */
159
+		if (cfg_get(sctp, cfg_h, assoc_reuse)!=0){
160
+			ERR("cannot turn sctp assoc_tracking off while assoc_reuse is"
161
+					" still on, please turn assoc_reuse off first\n");
162
+			return -1;
163
+		}
164
+		sctp_con_tracking_flush();
165
+	}else if (optval==1 && cfg_get(sctp, cfg_h, assoc_reuse)==0){
166
+		/* turning from off to on, make sure we flush the tracked list
167
+		   again, just incase the off flush was racing with a new connection*/
168
+		sctp_con_tracking_flush();
169
+	}
170
+#endif /* SCTP_CONN_REUSE */
171
+	return 0;
172
+}
173
+
174
+
175
+
176
+static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val)
177
+{
178
+	int optval;
179
+	
180
+	optval=(int)(long)(*val);
181
+#ifndef SCTP_CONN_REUSE
182
+	if (optval!=0){
183
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
184
+		return -1;
185
+	}
186
+#else /* SCTP_CONN_REUSE */
187
+	if (optval==1 && cfg_get(sctp, cfg_h, assoc_tracking)==0){
188
+		/* conn reuse on, but assoc_tracking off => not possible */
189
+		ERR("cannot turn sctp assoc_reuse on while assoc_tracking is"
190
+					" off, please turn assoc_tracking on first\n");
191
+		return -1;
192
+	}
193
+#endif /* SCTP_CONN_REUSE */
194
+	return 0;
195
+}
196
+
197
+
198
+
199
+static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val)
200
+{
201
+#ifdef SCTP_RTOINFO
202
+	struct sctp_rtoinfo rto;
203
+	SCTP_SET_SOCKOPT_DECLS;
204
+	
205
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
206
+		*val=(void*)(long)cfg_get(sctp, cfg_h, srto_initial);
207
+		return 0;
208
+	}
209
+	memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
210
+	rto.srto_assoc_id=0; /* all */
211
+	rto.srto_initial=(int)(long)(*val);
212
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
213
+							"cfg: setting SCTP_RTOINFO");
214
+#else
215
+	ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
216
+	return -1;
217
+#endif /* SCTP_RTOINFO */
218
+}
219
+
220
+
221
+
222
+static int set_srto_max(void* cfg_h, str* gname, str* name, void** val)
223
+{
224
+#ifdef SCTP_RTOINFO
225
+	struct sctp_rtoinfo rto;
226
+	SCTP_SET_SOCKOPT_DECLS;
227
+	
228
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
229
+		*val=(void*)(long)cfg_get(sctp, cfg_h, srto_max);
230
+		return 0;
231
+	}
232
+	memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
233
+	rto.srto_assoc_id=0; /* all */
234
+	rto.srto_max=(int)(long)(*val);
235
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
236
+							"cfg: setting SCTP_RTOINFO");
237
+#else
238
+	ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
239
+	return -1;
240
+#endif /* SCTP_RTOINFO */
67 241
 }
68 242
 
69 243
 
70 244
 
71
-void sctp_options_get(struct sctp_cfg_options *s)
245
+static int set_srto_min(void* cfg_h, str* gname, str* name, void** val)
72 246
 {
73
-	*s=sctp_options;
247
+#ifdef SCTP_RTOINFO
248
+	struct sctp_rtoinfo rto;
249
+	SCTP_SET_SOCKOPT_DECLS;
250
+	
251
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
252
+		*val=(void*)(long)cfg_get(sctp, cfg_h, srto_min);
253
+		return 0;
254
+	}
255
+	memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
256
+	rto.srto_assoc_id=0; /* all */
257
+	rto.srto_min=(int)(long)(*val);
258
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
259
+							"cfg: setting SCTP_RTOINFO");
260
+#else
261
+	ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
262
+	return -1;
263
+#endif /* SCTP_RTOINFO */
74 264
 }
265
+
266
+
267
+
268
+static int set_asocmaxrxt(void* cfg_h, str* gname, str* name, void** val)
269
+{
270
+#ifdef SCTP_ASSOCINFO
271
+	struct sctp_assocparams ap;
272
+	SCTP_SET_SOCKOPT_DECLS;
273
+	
274
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
275
+		*val=(void*)(long)cfg_get(sctp, cfg_h, asocmaxrxt);
276
+		return 0;
277
+	}
278
+	memset(&ap, 0, sizeof(ap)); /* zero everything we don't care about */
279
+	ap.sasoc_assoc_id=0; /* all */
280
+	ap.sasoc_asocmaxrxt=(int)(long)(*val);
281
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_ASSOCINFO, ap,
282
+							"cfg: setting SCTP_ASSOCINFO");
283
+#else
284
+	ERR("no SCTP_ASSOCINFO support, please upgrade your sctp library\n");
285
+	return -1;
286
+#endif /* SCTP_ASSOCINFO */
287
+}
288
+
289
+
290
+
291
+static int set_sinit_max_init_timeo(void* cfg_h, str* gname, str* name,
292
+									void** val)
293
+{
294
+#ifdef SCTP_INITMSG
295
+	struct sctp_initmsg im;
296
+	SCTP_SET_SOCKOPT_DECLS;
297
+	
298
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
299
+		*val=(void*)(long)cfg_get(sctp, cfg_h, init_max_timeo);
300
+		return 0;
301
+	}
302
+	memset(&im, 0, sizeof(im)); /* zero everything we don't care about */
303
+	im.sinit_max_init_timeo=(int)(long)(*val);
304
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_INITMSG, im,
305
+							"cfg: setting SCTP_INITMSG");
306
+#else
307
+	ERR("no SCTP_INITMSG support, please upgrade your sctp library\n");
308
+	return -1;
309
+#endif /* SCTP_INITMSG */
310
+}
311
+
312
+
313
+
314
+static int set_sinit_max_attempts(void* cfg_h, str* gname, str* name,
315
+									void** val)
316
+{
317
+#ifdef SCTP_INITMSG
318
+	struct sctp_initmsg im;
319
+	SCTP_SET_SOCKOPT_DECLS;
320
+	
321
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
322
+		*val=(void*)(long)cfg_get(sctp, cfg_h, init_max_attempts);
323
+		return 0;
324
+	}
325
+	memset(&im, 0, sizeof(im)); /* zero everything we don't care about */
326
+	im.sinit_max_attempts=(int)(long)(*val);
327
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_INITMSG, im,
328
+							"cfg: setting SCTP_INITMSG");
329
+#else
330
+	ERR("no SCTP_INITMSG support, please upgrade your sctp library\n");
331
+	return -1;
332
+#endif /* SCTP_INITMSG */
333
+}
334
+
335
+
336
+
337
+static int set_hbinterval(void* cfg_h, str* gname, str* name,
338
+									void** val)
339
+{
340
+#ifdef SCTP_PEER_ADDR_PARAMS
341
+	struct sctp_paddrparams pp;
342
+	SCTP_SET_SOCKOPT_DECLS;
343
+	
344
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
345
+		*val=(void*)(long)cfg_get(sctp, cfg_h, hbinterval);
346
+		return 0;
347
+	}
348
+	memset(&pp, 0, sizeof(pp)); /* zero everything we don't care about */
349
+	if ((int)(long)(*val)!=-1){
350
+		pp.spp_hbinterval=(int)(long)(*val);
351
+		pp.spp_flags=SPP_HB_ENABLE;
352
+	}else{
353
+		pp.spp_flags=SPP_HB_DISABLE;
354
+	}
355
+	err=0;
356
+	for (si=sctp_listen; si; si=si->next){
357
+		/* set the AF, needed on older linux kernels even for INADDR_ANY */
358
+		pp.spp_address.ss_family=si->address.af;
359
+		err+=(sctp_setsockopt(si->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
360
+								(void*)(&pp), sizeof(pp),
361
+								"cfg: setting SCTP_PEER_ADDR_PARAMS")<0);
362
+	}
363
+	return -(err!=0);
364
+#else
365
+	ERR("no SCTP_PEER_ADDR_PARAMS support, please upgrade your"
366
+			" sctp library\n");
367
+	return -1;
368
+#endif /* SCTP_PEER_ADDR_PARAMS */
369
+}
370
+
371
+
372
+
373
+static int set_pathmaxrxt(void* cfg_h, str* gname, str* name,
374
+									void** val)
375
+{
376
+#ifdef SCTP_PEER_ADDR_PARAMS
377
+	struct sctp_paddrparams pp;
378
+	SCTP_SET_SOCKOPT_DECLS;
379
+	
380
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
381
+		*val=(void*)(long)cfg_get(sctp, cfg_h, pathmaxrxt);
382
+		return 0;
383
+	}
384
+	memset(&pp, 0, sizeof(pp)); /* zero everything we don't care about */
385
+	pp.spp_pathmaxrxt=(int)(long)(*val);
386
+	err=0;
387
+	for (si=sctp_listen; si; si=si->next){
388
+		/* set the AF, needed on older linux kernels even for INADDR_ANY */
389
+		pp.spp_address.ss_family=si->address.af;
390
+		err+=(sctp_setsockopt(si->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
391
+								(void*)(&pp), sizeof(pp),
392
+								"cfg: setting SCTP_PEER_ADDR_PARAMS")<0);
393
+	}
394
+	return -(err!=0);
395
+#else
396
+	ERR("no SCTP_PEER_ADDR_PARAMS support, please upgrade your"
397
+			" sctp library\n");
398
+	return -1;
399
+#endif /* SCTP_PEER_ADDR_PARAMS */
400
+}
401
+
402
+
403
+
404
+static int set_sack_delay(void* cfg_h, str* gname, str* name, void** val)
405
+{
406
+#if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
407
+#ifdef SCTP_DELAYED_SACK
408
+	struct sctp_sack_info sa;
409
+#else /* old lib */
410
+	struct sctp_assoc_value sa;
411
+#endif /* SCTP_DELAYED_SACK */
412
+	SCTP_SET_SOCKOPT_DECLS;
413
+	
414
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
415
+		*val=(void*)(long)cfg_get(sctp, cfg_h, sack_delay);
416
+		return 0;
417
+	}
418
+	memset(&sa, 0, sizeof(sa)); /* zero everything we don't care about */
419
+#ifdef SCTP_DELAYED_SACK
420
+	sa.sack_delay=(int)(long)(*val);
421
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_SACK, sa,
422
+							"cfg: setting SCTP_DELAYED_SACK");
423
+#else /* old sctp lib version which uses SCTP_DELAYED_ACK_TIME */
424
+	sa.assoc_value=(int)(long)(*val);
425
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME, sa,
426
+							"cfg: setting SCTP_DELAYED_ACK_TIME");
427
+#endif /* SCTP_DELAYED_SACK */
428
+#else
429
+	ERR("no SCTP_DELAYED_SACK support, please upgrade your sctp library\n");
430
+	return -1;
431
+#endif /* SCTP_DELAYED_SACK | SCTP_DELAYED_ACK_TIME */
432
+}
433
+
434
+
435
+
436
+static int set_sack_freq(void* cfg_h, str* gname, str* name, void** val)
437
+{
438
+#ifdef SCTP_DELAYED_SACK
439
+	struct sctp_sack_info sa;
440
+	SCTP_SET_SOCKOPT_DECLS;
441
+	
442
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
443
+		*val=(void*)(long)cfg_get(sctp, cfg_h, sack_freq);
444
+		return 0;
445
+	}
446
+	memset(&sa, 0, sizeof(sa)); /* zero everything we don't care about */
447
+	sa.sack_freq=(int)(long)(*val);
448
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_SACK, sa,
449
+							"cfg: setting SCTP_DELAYED_SACK");
450
+#else
451
+	ERR("no SCTP_DELAYED_SACK support, please upgrade your sctp library\n");
452
+	return -1;
453
+#endif /* SCTP_DELAYED_SACK */
454
+}
455
+
456
+
457
+
458
+static int set_max_burst(void* cfg_h, str* gname, str* name, void** val)
459
+{
460
+#ifdef SCTP_MAX_BURST
461
+	struct sctp_assoc_value av;
462
+	SCTP_SET_SOCKOPT_DECLS;
463
+	
464
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
465
+		*val=(void*)(long)cfg_get(sctp, cfg_h, max_burst);
466
+		return 0;
467
+	}
468
+	memset(&av, 0, sizeof(av)); /* zero everything we don't care about */
469
+	av.assoc_value=(int)(long)(*val);
470
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_MAX_BURST, av,
471
+							"cfg: setting SCTP_MAX_BURST");
472
+#else
473
+	ERR("no SCTP_MAX_BURST support, please upgrade your sctp library\n");
474
+	return -1;
475
+#endif /* SCTP_MAX_BURST */
476
+}
477
+
478
+#endif /* USE_SCTP */
... ...
@@ -22,29 +22,55 @@
22 22
  * History:
23 23
  * --------
24 24
  *  2008-08-07  initial version (andrei)
25
+ *  2009-05-26  runtime cfg support (andrei)
25 26
  */
26 27
 
27 28
 #ifndef _sctp_options_h
28 29
 #define _sctp_options_h
29 30
 
31
+#ifndef NO_SCTP_CONN_REUSE
32
+/* SCTP connection reuse by default */
33
+#define SCTP_CONN_REUSE
34
+#endif
35
+
30 36
 #define DEFAULT_SCTP_AUTOCLOSE 180 /* seconds */
31 37
 #define DEFAULT_SCTP_SEND_TTL  32000 /* in ms (32s)  */
32 38
 #define DEFAULT_SCTP_SEND_RETRIES 0
33 39
 #define MAX_SCTP_SEND_RETRIES 9
34 40
 
35 41
 
36
-struct sctp_cfg_options{
37
-	int sctp_so_rcvbuf;
38
-	int sctp_so_sndbuf;
39
-	unsigned int sctp_autoclose; /* in seconds */
40
-	unsigned int sctp_send_ttl; /* in milliseconds */
41
-	unsigned int sctp_send_retries;
42
+struct cfg_group_sctp{
43
+	int so_rcvbuf;
44
+	int so_sndbuf;
45
+	unsigned int autoclose; /* in seconds */
46
+	unsigned int send_ttl; /* in milliseconds */
47
+	unsigned int send_retries;
48
+	int assoc_tracking; /* track associations */
49
+	int assoc_reuse; /* reuse the request connection for sending the reply,
50
+					    depends on assoc_tracking */
51
+	int max_assocs; /* maximum associations, -1 means disabled */
52
+	unsigned int srto_initial; /** initial retr. timeout */
53
+	unsigned int srto_max;     /** max retr. timeout */
54
+	unsigned int srto_min;     /** min retr. timeout */
55
+	unsigned int asocmaxrxt; /** max. retr. attempts per association */
56
+	unsigned int init_max_attempts; /** max., INIT retr. attempts */
57
+	unsigned int init_max_timeo; /** rto max for INIT */
58
+	unsigned int hbinterval;  /** heartbeat interval in msecs */
59
+	unsigned int pathmaxrxt;  /** max. retr. attempts per path */
60
+	unsigned int sack_delay; /** msecs after which a delayed SACK is sent */
61
+	unsigned int sack_freq; /** no. of packets after which a SACK is sent */
62
+	unsigned int max_burst; /** maximum burst of packets per assoc. */
42 63
 };
43 64
 
44
-extern struct sctp_cfg_options sctp_options;
65
+extern struct cfg_group_sctp sctp_default_cfg;
66
+
67
+/* sctp config handle */
68
+extern void* sctp_cfg;
45 69
 
46 70
 void init_sctp_options();
47 71
 void sctp_options_check();
48
-void sctp_options_get(struct sctp_cfg_options *s);
72
+int sctp_register_cfg();
73
+void sctp_options_get(struct cfg_group_sctp *s);
74
+int sctp_get_os_defaults(struct cfg_group_sctp *s);
49 75
 
50 76
 #endif /* _sctp_options_h */
... ...
@@ -65,6 +65,10 @@
65 65
 
66 66
 static atomic_t* sctp_conn_no;
67 67
 
68
+
69
+#define ABORT_REASON_MAX_ASSOCS \
70
+	"Maximum configured number of open associations exceeded"
71
+
68 72
 /* check if the underlying OS supports sctp
69 73
    returns 0 if yes, -1 on error */
70 74
 int sctp_check_support()
... ...
@@ -185,20 +189,222 @@ error:
185 185
 
186 186
 
187 187
 
188
+/** set a socket option (wrapper over setsockopt).
189
+  * @param err_prefix - if 0 no error message is printed on failure, if !=0
190
+  *                     it will be prepended to the error message.
191
+  * @return 0 on success, -1 on error */
192
+int sctp_setsockopt(int s, int level, int optname, 
193
+					void* optval, socklen_t optlen, char* err_prefix)
194
+{
195
+	if (setsockopt(s, level, optname, optval, optlen) ==-1){
196
+		if (err_prefix)
197
+			ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
198
+		return -1;
199
+	}
200
+	return 0;
201
+}
202
+
203
+
204
+
205
+/** get a socket option (wrapper over getsockopt).
206
+  * @param err_prefix - if 0 no error message is printed on failure, if !=0
207
+  *                     it will be prepended to the error message.
208
+  * @return 0 on success, -1 on error */
209
+int sctp_getsockopt(int s, int level, int optname, 
210
+					void* optval, socklen_t* optlen, char* err_prefix)
211
+{
212
+	if (getsockopt(s, level, optname, optval, optlen) ==-1){
213
+		if (err_prefix)
214
+			ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
215
+		return -1;
216
+	}
217
+	return 0;
218
+}
219
+
220
+
221
+
222
+/** get the os defaults for cfg options with os correspondents.
223
+ *  @param s - intialized sctp socket
224
+ *  @param cfg - filled with the os defaults
225
+ *  @return -1 on error, 0 on success
226
+ */
227
+int sctp_get_os_defaults(struct cfg_group_sctp* cfg)
228
+{
229
+	int optval;
230
+	socklen_t optlen;
231
+	int s;
232
+#ifdef SCTP_RTOINFO
233
+	struct sctp_rtoinfo rto;
234
+#endif /* SCTP_RTOINFO */
235
+#ifdef SCTP_ASSOCINFO
236
+	struct sctp_assocparams ap;
237
+#endif /* SCTP_ASSOCINFO */
238
+#ifdef SCTP_INITMSG
239
+	struct sctp_initmsg im;
240
+#endif /* SCTP_INITMSG */
241
+#ifdef SCTP_PEER_ADDR_PARAMS
242
+	struct sctp_paddrparams pp;
243
+#endif /* SCTP_PEER_ADDR_PARAMS */
244
+#ifdef SCTP_DELAYED_SACK
245
+	struct sctp_sack_info sa;
246
+#elif defined SCTP_DELAYED_ACK_TIME /* old version */
247
+	struct sctp_assoc_value sa;
248
+#endif /* SCTP_DELAYED_SACK */
249
+#ifdef SCTP_MAX_BURST
250
+	struct sctp_assoc_value av;
251
+#endif /* SCTP_MAX_BURST */
252
+	
253
+	s = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
254
+	if (s==-1)
255
+		return -1;
256
+	
257
+	/* SO_RCVBUF */
258
+	optlen=sizeof(int);
259
+	if (sctp_getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&optval,
260
+							&optlen, "SO_RCVBUF")==0){
261
+		/* success => hack to set the "default" values*/
262
+		#ifdef __OS_linux
263
+			optval/=2; /* in linux getsockopt() returns 2*set_value */
264
+		#endif
265
+		cfg->so_rcvbuf=optval;
266
+	}
267
+	/* SO_SNDBUF */
268
+	optlen=sizeof(int);
269
+	if (sctp_getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&optval,
270
+							&optlen, "SO_SNDBUF")==0){
271
+		/* success => hack to set the "default" values*/
272
+		#ifdef __OS_linux
273
+			optval/=2; /* in linux getsockopt() returns 2*set_value */
274
+		#endif
275
+		cfg->so_sndbuf=optval;
276
+	}
277
+	/* SCTP_RTOINFO -> srto_initial, srto_min, srto_max */
278
+#ifdef SCTP_RTOINFO
279
+	optlen=sizeof(rto);
280
+	rto.srto_assoc_id=0;
281
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
282
+							&optlen, "SCTP_RTOINFO")==0){
283
+		/* success => hack to set the "default" values*/
284
+		cfg->srto_initial=rto.srto_initial;
285
+		cfg->srto_min=rto.srto_min;
286
+		cfg->srto_max=rto.srto_max;
287
+	}
288
+#endif /* SCTP_RTOINFO */
289
+#ifdef SCTP_ASSOCINFO
290
+	optlen=sizeof(ap);
291
+	ap.sasoc_assoc_id=0;
292
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_ASSOCINFO, (void*)&ap,
293
+							&optlen, "SCTP_ASSOCINFO")==0){
294
+		/* success => hack to set the "default" values*/
295
+		cfg->asocmaxrxt=ap.sasoc_asocmaxrxt;
296
+	}
297
+#endif /* SCTP_ASSOCINFO */
298
+#ifdef SCTP_INITMSG
299
+	optlen=sizeof(im);
300
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, (void*)&im,
301
+							&optlen, "SCTP_INITMSG")==0){
302
+		/* success => hack to set the "default" values*/
303
+		cfg->init_max_attempts=im.sinit_max_attempts;
304
+		cfg->init_max_timeo=im.sinit_max_init_timeo;
305
+	}
306
+#endif /* SCTP_INITMSG */
307
+#ifdef SCTP_PEER_ADDR_PARAMS
308
+	optlen=sizeof(pp);
309
+	memset(&pp, 0, sizeof(pp)); /* get defaults */
310
+	/* set the AF, needed on older linux kernels even for INADDR_ANY */
311
+	pp.spp_address.ss_family=AF_INET;
312
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, (void*)&pp,
313
+							&optlen, "SCTP_PEER_ADDR_PARAMS")==0){
314
+		/* success => hack to set the "default" values*/
315
+		cfg->hbinterval=pp.spp_hbinterval;
316
+		cfg->pathmaxrxt=pp.spp_pathmaxrxt;
317
+	}
318
+#endif /* SCTP_PEER_ADDR_PARAMS */
319
+#if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
320
+	optlen=sizeof(sa);
321
+	memset(&sa, 0, sizeof(sa));
322
+#ifdef SCTP_DELAYED_SACK
323
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_SACK, (void*)&sa,
324
+							&optlen, "SCTP_DELAYED_SACK")==0){
325
+		/* success => hack to set the "default" values*/
326
+		cfg->sack_delay=sa.sack_delay;
327
+		cfg->sack_freq=sa.sack_freq;
328
+	}
329
+#else /* old sctp lib version which uses SCTP_DELAYED_ACK_TIME */
330
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME, (void*)&sa,
331
+							&optlen, "SCTP_DELAYED_ACK_TIME")==0){
332
+		/* success => hack to set the "default" values*/
333
+		cfg->sack_delay=sa.assoc_value;
334
+		cfg->sack_freq=0; /* unknown */
335
+	}
336
+#endif /* SCTP_DELAYED_SACK */
337
+#endif /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
338
+#ifdef SCTP_MAX_BURST
339
+	optlen=sizeof(av);
340
+	av.assoc_id=0;
341
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_MAX_BURST, (void*)&av,
342
+							&optlen, "SCTP_MAX_BURST")==0){
343
+		/* success => hack to set the "default" values*/
344
+		cfg->max_burst=av.assoc_value;
345
+	}
346
+#endif /* SCTP_MAX_BURST */
347
+	
348
+	close(s);
349
+	return 0;
350
+}
351
+
352
+
353
+
188 354
 /* set common (for one to many and one to one) sctp socket options
189 355
    tries to ignore non-critical errors (it will only log them), for
190 356
    improved portability (for example older linux kernel version support
191 357
    only a limited number of sctp socket options)
192 358
    returns 0 on success, -1 on error
193 359
    WARNING: please keep it sync'ed w/ sctp_check_compiled_sockopts() */
194
-static int sctp_init_sock_opt_common(int s)
360
+static int sctp_init_sock_opt_common(int s, int af)
195 361
 {
196
-	struct sctp_event_subscribe es;
197 362
 	int optval;
363
+	int pd_point;
364
+	int saved_errno;
198 365
 	socklen_t optlen;
199 366
 	int sctp_err;
367
+#ifdef SCTP_RTOINFO
368
+	struct sctp_rtoinfo rto;
369
+#endif /* SCTP_RTOINFO */
370
+#ifdef SCTP_ASSOCINFO
371
+	struct sctp_assocparams ap;
372
+#endif /* SCTP_ASSOCINFO */
373
+#ifdef SCTP_INITMSG
374
+	struct sctp_initmsg im;
375
+#endif /* SCTP_INITMSG */
376
+#ifdef SCTP_PEER_ADDR_PARAMS
377
+	struct sctp_paddrparams pp;
378
+#endif /* SCTP_PEER_ADDR_PARAMS */
379
+#ifdef SCTP_DELAYED_SACK
380
+	struct sctp_sack_info sa;
381
+#elif defined SCTP_DELAYED_ACK_TIME /* old version */
382
+	struct sctp_assoc_value sa;
383
+#endif /* SCTP_DELAYED_SACK */
384
+#ifdef SCTP_MAX_BURST
385
+	struct sctp_assoc_value av;
386
+#endif /* SCTP_MAX_BURST */
387
+	
388
+#ifdef __OS_linux
389
+	union {
390
+		struct sctp_event_subscribe s;
391
+		char padding[sizeof(struct sctp_event_subscribe)+sizeof(__u8)];
392
+	} es;
393
+#else
394
+	struct sctp_event_subscribe es;
395
+#endif
396
+	struct sctp_event_subscribe* ev_s;
200 397
 	
201 398
 	sctp_err=0;
399
+#ifdef __OS_linux
400
+	ev_s=&es.s;
401
+#else
402
+	ev_s=&es;
403
+#endif
202 404
 	/* set tos */
203 405
 	optval = tos;
204 406
 	if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval,sizeof(optval)) ==-1){
... ...
@@ -208,8 +414,8 @@ static int sctp_init_sock_opt_common(int s)
208 208
 	}
209 209
 	
210 210
 	/* set receive buffer: SO_RCVBUF*/
211
-	if (sctp_options.sctp_so_rcvbuf){
212
-		optval=sctp_options.sctp_so_rcvbuf;
211
+	if (cfg_get(sctp, sctp_cfg, so_rcvbuf)){
212
+		optval=cfg_get(sctp, sctp_cfg, so_rcvbuf);
213 213
 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
214 214
 					(void*)&optval, sizeof(optval)) ==-1){
215 215
 			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
... ...
@@ -219,8 +425,8 @@ static int sctp_init_sock_opt_common(int s)
219 219
 	}
220 220
 	
221 221
 	/* set send buffer: SO_SNDBUF */
222
-	if (sctp_options.sctp_so_sndbuf){
223
-		optval=sctp_options.sctp_so_sndbuf;
222
+	if (cfg_get(sctp, sctp_cfg, so_sndbuf)){
223
+		optval=cfg_get(sctp, sctp_cfg, so_sndbuf);
224 224
 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
225 225
 					(void*)&optval, sizeof(optval)) ==-1){
226 226
 			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
... ...
@@ -267,13 +473,34 @@ static int sctp_init_sock_opt_common(int s)
267 267
 		/* try to continue */
268 268
 		optval=0;
269 269
 	}
270
-	if (setsockopt(s, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
271
-					(void*)&optval, sizeof(optval)) ==-1){
272
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
270
+#ifdef __OS_linux
271
+	optval/=2; /* in linux getsockopt() returns twice the set value */
272
+#endif
273
+	pd_point=optval;
274
+	saved_errno=0;
275
+	while(pd_point &&
276
+			setsockopt(s, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
277
+					(void*)&pd_point, sizeof(pd_point)) ==-1){
278
+		if (!saved_errno)
279
+			saved_errno=errno;
280
+		pd_point--;
281
+	}
282
+	
283
+	if (pd_point!=optval){
284
+		if (pd_point==0){
285
+			/* all attempts failed */
286
+			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
273 287
 						"SCTP_PARTIAL_DELIVERY_POINT (%d): %s\n",
274 288
 						optval, strerror(errno));
275
-		sctp_err++;
276
-		/* try to continue */
289
+			sctp_err++;
290
+			/* try to continue */
291
+		}else{
292
+			/* success but to a lower value (might not be disabled) */
293
+			LOG(L_WARN, "setsockopt SCTP_PARTIAL_DELIVERY_POINT set to %d, but"
294
+				" the socket rcvbuf is %d (higher values fail with"
295
+				" \"%s\" [%d])\n",
296
+				pd_point, optval, strerror(saved_errno), saved_errno);
297
+		}
277 298
 	}
278 299
 #else
279 300
 #warning no sctp lib support for SCTP_PARTIAL_DELIVERY_POINT, consider upgrading
... ...
@@ -309,7 +536,7 @@ static int sctp_init_sock_opt_common(int s)
309 309
 	
310 310
 	/* set autoclose */
311 311
 #ifdef SCTP_AUTOCLOSE
312
-	optval=sctp_options.sctp_autoclose;
312
+	optval=cfg_get(sctp, sctp_cfg, autoclose);
313 313
 	if (setsockopt(s, IPPROTO_SCTP, SCTP_AUTOCLOSE,
314 314
 					(void*)&optval, sizeof(optval)) ==-1){
315 315
 		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
... ...
@@ -322,31 +549,171 @@ static int sctp_init_sock_opt_common(int s)
322 322
 #else
323 323
 #error SCTP_AUTOCLOSE not supported, please upgrade your sctp library
324 324
 #endif /* SCTP_AUTOCLOSE */
325
+	/* set rtoinfo options: srto_initial, srto_min, srto_max */
326
+#ifdef SCTP_RTOINFO
327
+	memset(&rto, 0, sizeof(rto));
328
+	rto.srto_initial=cfg_get(sctp, sctp_cfg, srto_initial);
329
+	rto.srto_min=cfg_get(sctp, sctp_cfg, srto_min);
330
+	rto.srto_max=cfg_get(sctp, sctp_cfg, srto_max);
331
+	if (rto.srto_initial || rto.srto_min || rto.srto_max){
332
+		/* if at least one is non-null => we have to set it */
333
+		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
334
+							sizeof(rto), "setsockopt: SCTP_RTOINFO")!=0){
335
+			sctp_err++;
336
+			/* non critical, try to continue */
337
+		}
338
+	}
339
+#else
340