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 354
                       machine. WARNING: use with care and low values (e.g.
350 355
                       1-3) to avoid "multiplying" traffic to unresponding 
351 356
                       hosts (default: 0).
357
+                      Can be changed at runtime.
358
+  sctp_assoc_tracking = yes/no - controls whether or not sctp associations
359
+     are tracked inside ser/sip-router. Turning it off would result in
360
+     less memory being used and slightly better performance, but it will also
361
+     disable some other features that depend on it (e.g. sctp_assoc_reuse).
362
+     Default: yes.
363
+     Can be changed at runtime (sercmd sctp assoc_tracking 0), but changes
364
+     will be allowed only if all the other features that depend on it are
365
+     turned off (for example it can be turned off only if first
366
+     sctp_assoc_reuse was turned off).
367
+     Note: turning sctp_assoc_tracking on/off will delete all the tracking
368
+     information for all the currently tracked associations and might introduce
369
+     a small temporary delay in the sctp processing if lots of associations
370
+     were tracked.
371
+     Config options depending on sctp_assoc_tracking being on:
372
+      sctp_assoc_reuse.
373
+  sctp_assoc_reuse = yes/no - controls sctp association reuse. For now only
374
+     association reuse for replies is affected by it. Default: yes.
375
+     Depends on sctp_assoc_tracking being on.
376
+     Note that even if turned off, if the port in via corresponds to the
377
+     source port of the association the request was sent on or if rport is
378
+     turned on (force_rport() or via containing a rport option), the
379
+     association will be automatically reused by the sctp stack.
380
+     Can be changed at runtime (sctp assoc_reuse), but it can be turned on
381
+     only if sctp_assoc_tracking is on.
382
+  sctp_max_assocs = number - maximum number of allowed open sctp associations.
383
+     -1 means maximum allowed by the OS. Default: -1.
384
+     Can be changed at runtime (e.g.:
385
+      sercmd cfg.set_now_int sctp max_assocs 10 ).
386
+     When the maximum associations number is exceeded and a new associations
387
+     is opened by a remote host, the association will be immediately closed.
388
+     However it is possible that some sip packets get through (especially if
389
+     they are sent early, as part of the 4-way handshake).
390
+     When ser/sip-router tries to open a new association and the max_assocs
391
+     is exceeded the exact behaviour depends on whether or not
392
+     sctp_assoc_tracking is on. If on, the send triggering the active open
393
+     will gracefully fail, before actually opening the new association and no
394
+     packet will be sent. However if sctp_assoc_tracking is off, the
395
+     association will first be opened and then immediately closed. In general
396
+     this means that the initial sip packet will be sent (as part of the 4-way
397
+     handshake).
398
+  sctp_srto_initial = milliseconds - initial value of the retr. timeout, used
399
+     in RTO calculations (default: OS specific).
400
+     Can be changed at runtime (sctp srto_initial) but it will affect only new
401
+     associations.
402
+  sctp_srto_max = milliseconds - maximum value of the retransmission timeout
403
+     (RTO) (default: OS specific).
404
+     WARNING: values lower then the sctp sack_delay will cause lots of
405
+     retransmissions and connection instability (see sctp_srto_min for more
406
+     details).
407
+     Can be changed at runtime (sctp srto_max) but it will affect only new
408
+     associations.
409
+  sctp_srto_min = milliseconds - minimum value of the retransmission timeout
410
+     (RTO) (default: OS specific).
411
+     WARNING: values lower then the sctp sack_delay of any peer might cause
412
+     retransmissions and possible interoperability problems. According to the
413
+     standard the sack_delay should be between 200 and 500 ms, so avoid trying
414
+     values lower then 500 ms unless you control all the possible sctp peers
415
+     and you do make sure their sack_delay is higher or their sack_freq is 1.
416
+     Can be changed at runtime (sctp srto_min) but it will affect only new
417
+     associations.
418
+  sctp_asocmaxrxt   = number - maximum retransmissions attempts per association
419
+     (default: OS specific). It should be set to sctp_pathmaxrxt * no. of
420
+     expected paths.
421
+     Can be changed at runtime (sctp asocmaxrxt) but it will affect only new
422
+     associations.
423
+  sctp_init_max_attempts = number - maximum INIT retransmission attempts
424
+     (default: OS specific).
425
+     Can be changed at runtime (sctp init_max_attempts).
426
+  sctp_init_max_timeo = milliseconds - maximum INIT retransmission timeout (RTO
427
+     max for INIT). Default: OS specific.
428
+     Can be changed at runtime (sctp init_max_timeo).
429
+  sctp_hbinterval = milliseconds - sctp heartbeat interval. Setting it to -1
430
+     will disable the heartbeats. Default: OS specific.
431
+     Can be changed at runtime (sctp hbinterval) but it will affect only new
432
+     associations.
433
+  sctp_pathmaxrxt = number - maximum retransmission attempts per path (see also
434
+     sctp_asocmaxrxt). Default: OS specific.
435
+     Can be changed at runtime (sctp pathmaxrxt) but it will affect only new
436
+     associations.
437
+  sctp_sack_delay = milliseconds - delay until an ACK is generated after
438
+     receiving a packet. Default: OS specific.
439
+     WARNING: a value higher then srto_min can cause a lot of retransmissions
440
+     (and strange problems). A value higher then srto_max will result in very
441
+     high connections instability. According to the standard the sack_delay
442
+     value should be between 200 and 500 ms.
443
+     Can be changed at runtime (sctp sack_delay) but it will affect only new
444
+     associations.
445
+  sctp_sack_freq = number - number of packets received before an ACK is sent
446
+     (without waiting for the sack_delay to expire).  Default: OS specific.
447
+     Note: on linux with lksctp up to and including 1.0.9 is not possible to
448
+     set this value (having it in the config will produce a warning on
449
+     startup).
450
+     Can be changed at runtime (sctp sack_freq) but it will affect only new
451
+     associations.
452
+  sctp_max_burst = number - maximum burst of packets that can be emitted by an
453
+     association. Default: OS specific.
454
+     Can be changed at runtime (sctp max_burst) but it will affect only new 
455
+     associations.
352 456
   server_id = number - A configurable unique server id that can be used to
353 457
                        discriminate server instances within a cluster of
354 458
                        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 730
 										return SCTP_SEND_TTL; }
716 731
 <INITIAL>{SCTP_SEND_RETRIES}	{ count(); yylval.strval=yytext;
717 732
 										return SCTP_SEND_RETRIES; }
733
+<INITIAL>{SCTP_ASSOC_TRACKING}	{ count(); yylval.strval=yytext;
734
+										return SCTP_ASSOC_TRACKING; }
735
+<INITIAL>{SCTP_ASSOC_REUSE}		{ count(); yylval.strval=yytext;
736
+										return SCTP_ASSOC_REUSE; }
737
+<INITIAL>{SCTP_MAX_ASSOCS}		{ count(); yylval.strval=yytext;
738
+										return SCTP_MAX_ASSOCS; }
739
+<INITIAL>{SCTP_SRTO_INITIAL}	{ count(); yylval.strval=yytext;
740
+										return SCTP_SRTO_INITIAL; }
741
+<INITIAL>{SCTP_SRTO_MAX}	{ count(); yylval.strval=yytext;
742
+										return SCTP_SRTO_MAX; }
743
+<INITIAL>{SCTP_SRTO_MIN}	{ count(); yylval.strval=yytext;
744
+										return SCTP_SRTO_MIN; }
745
+<INITIAL>{SCTP_ASOCMAXRXT}	{ count(); yylval.strval=yytext;
746
+										return SCTP_ASOCMAXRXT; }
747
+<INITIAL>{SCTP_INIT_MAX_ATTEMPTS}	{ count(); yylval.strval=yytext;
748
+										return SCTP_INIT_MAX_ATTEMPTS; }
749
+<INITIAL>{SCTP_INIT_MAX_TIMEO}	{ count(); yylval.strval=yytext;
750
+										return SCTP_INIT_MAX_TIMEO; }
751
+<INITIAL>{SCTP_HBINTERVAL}	{ count(); yylval.strval=yytext;
752
+										return SCTP_HBINTERVAL; }
753
+<INITIAL>{SCTP_PATHMAXRXT}	{ count(); yylval.strval=yytext;
754
+										return SCTP_PATHMAXRXT; }
755
+<INITIAL>{SCTP_SACK_DELAY}	{ count(); yylval.strval=yytext;
756
+										return SCTP_SACK_DELAY; }
757
+<INITIAL>{SCTP_SACK_FREQ}	{ count(); yylval.strval=yytext;
758
+										return SCTP_SACK_FREQ; }
759
+<INITIAL>{SCTP_MAX_BURST}	{ count(); yylval.strval=yytext;
760
+										return SCTP_MAX_BURST; }
718 761
 <INITIAL>{SERVER_SIGNATURE}	{ count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
719 762
 <INITIAL>{REPLY_TO_VIA}	{ count(); yylval.strval=yytext; return REPLY_TO_VIA; }
720 763
 <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 445
 %token SCTP_AUTOCLOSE
440 446
 %token SCTP_SEND_TTL
441 447
 %token SCTP_SEND_RETRIES
448
+%token SCTP_ASSOC_TRACKING
449
+%token SCTP_ASSOC_REUSE
450
+%token SCTP_MAX_ASSOCS
451
+%token SCTP_SRTO_INITIAL
452
+%token SCTP_SRTO_MAX
453
+%token SCTP_SRTO_MIN
454
+%token SCTP_ASOCMAXRXT
455
+%token SCTP_INIT_MAX_ATTEMPTS
456
+%token SCTP_INIT_MAX_TIMEO
457
+%token SCTP_HBINTERVAL
458
+%token SCTP_PATHMAXRXT
459
+%token SCTP_SACK_DELAY
460
+%token SCTP_SACK_FREQ
461
+%token SCTP_MAX_BURST
442 462
 %token ADVERTISED_ADDRESS
443 463
 %token ADVERTISED_PORT
444 464
 %token DISABLE_CORE
... ...
@@ -1214,7 +1234,7 @@ assign_stm:
1214 1234
 	| SCTP_CHILDREN EQUAL error { yyerror("number expected"); }
1215 1235
 	| SCTP_SOCKET_RCVBUF EQUAL NUMBER {
1216 1236
 		#ifdef USE_SCTP
1217
-			sctp_options.sctp_so_rcvbuf=$3;
1237
+			sctp_default_cfg.so_rcvbuf=$3;
1218 1238
 		#else
1219 1239
 			warn("sctp support not compiled in");
1220 1240
 		#endif
... ...
@@ -1222,7 +1242,7 @@ assign_stm:
1222 1242
 	| SCTP_SOCKET_RCVBUF EQUAL error { yyerror("number expected"); }
1223 1243
 	| SCTP_SOCKET_SNDBUF EQUAL NUMBER {
1224 1244
 		#ifdef USE_SCTP
1225
-			sctp_options.sctp_so_sndbuf=$3;
1245
+			sctp_default_cfg.so_sndbuf=$3;
1226 1246
 		#else
1227 1247
 			warn("sctp support not compiled in");
1228 1248
 		#endif
... ...
@@ -1230,7 +1250,7 @@ assign_stm:
1230 1250
 	| SCTP_SOCKET_SNDBUF EQUAL error { yyerror("number expected"); }
1231 1251
 	| SCTP_AUTOCLOSE EQUAL NUMBER {
1232 1252
 		#ifdef USE_SCTP
1233
-			sctp_options.sctp_autoclose=$3;
1253
+			sctp_default_cfg.autoclose=$3;
1234 1254
 		#else
1235 1255
 			warn("sctp support not compiled in");
1236 1256
 		#endif
... ...
@@ -1238,7 +1258,7 @@ assign_stm:
1238 1258
 	| SCTP_AUTOCLOSE EQUAL error { yyerror("number expected"); }
1239 1259
 	| SCTP_SEND_TTL EQUAL NUMBER {
1240 1260
 		#ifdef USE_SCTP
1241
-			sctp_options.sctp_send_ttl=$3;
1261
+			sctp_default_cfg.send_ttl=$3;
1242 1262
 		#else
1243 1263
 			warn("sctp support not compiled in");
1244 1264
 		#endif
... ...
@@ -1246,12 +1266,88 @@ assign_stm:
1246 1266
 	| SCTP_SEND_TTL EQUAL error { yyerror("number expected"); }
1247 1267
 	| SCTP_SEND_RETRIES EQUAL NUMBER {
1248 1268
 		#ifdef USE_SCTP
1249
-			sctp_options.sctp_send_retries=$3;
1269
+			sctp_default_cfg.send_retries=$3;
1250 1270
 		#else
1251 1271
 			warn("sctp support not compiled in");
1252 1272
 		#endif
1253 1273
 	}
1254 1274
 	| SCTP_SEND_RETRIES EQUAL error { yyerror("number expected"); }
1275
+	| SCTP_ASSOC_TRACKING EQUAL NUMBER {
1276
+		#ifdef USE_SCTP
1277
+			#ifdef SCTP_CONN_REUSE
1278
+				sctp_default_cfg.assoc_tracking=$3;
1279
+			#else
1280
+				if ($3)
1281
+					warn("sctp association tracking/reuse (SCTP_CONN_REUSE) "
1282
+							"support not compiled in");
1283
+			#endif /* SCTP_CONN_REUSE */
1284
+		#else
1285
+			warn("sctp support not compiled in");
1286
+		#endif /* USE_SCTP */
1287
+	}
1288
+	| SCTP_ASSOC_TRACKING EQUAL error { yyerror("number expected"); }
1289
+	| SCTP_ASSOC_REUSE EQUAL NUMBER {
1290
+		#ifdef USE_SCTP
1291
+			#ifdef SCTP_CONN_REUSE
1292
+				sctp_default_cfg.assoc_reuse=$3;
1293
+			#else
1294
+				if ($3)
1295
+					warn("sctp association reuse (SCTP_CONN_REUSE) support"
1296
+							" not compiled in");
1297
+			#endif /* SCTP_CONN_REUSE */
1298
+		#else
1299
+			warn("sctp support not compiled in");
1300
+		#endif /* USE_SCTP */
1301
+	}
1302
+	| SCTP_ASSOC_REUSE EQUAL error { yyerror("number expected"); }
1303
+	| SCTP_MAX_ASSOCS EQUAL NUMBER {
1304
+			IF_SCTP(sctp_default_cfg.max_assocs=$3);
1305
+	}
1306
+	| SCTP_MAX_ASSOCS EQUAL error { yyerror("number expected"); }
1307
+	| SCTP_SRTO_INITIAL EQUAL NUMBER {
1308
+			IF_SCTP(sctp_default_cfg.srto_initial=$3);
1309
+	}
1310
+	| SCTP_SRTO_INITIAL EQUAL error { yyerror("number expected"); }
1311
+	| SCTP_SRTO_MAX EQUAL NUMBER {
1312
+			IF_SCTP(sctp_default_cfg.srto_max=$3);
1313
+	}
1314
+	| SCTP_SRTO_MAX EQUAL error { yyerror("number expected"); }
1315
+	| SCTP_SRTO_MIN EQUAL NUMBER {
1316
+			IF_SCTP(sctp_default_cfg.srto_min=$3);
1317
+	}
1318
+	| SCTP_SRTO_MIN EQUAL error { yyerror("number expected"); }
1319
+	| SCTP_ASOCMAXRXT EQUAL NUMBER {
1320
+			IF_SCTP(sctp_default_cfg.asocmaxrxt=$3);
1321
+	}
1322
+	| SCTP_ASOCMAXRXT EQUAL error { yyerror("number expected"); }
1323
+	| SCTP_INIT_MAX_ATTEMPTS EQUAL NUMBER {
1324
+			IF_SCTP(sctp_default_cfg.init_max_attempts=$3);
1325
+	}
1326
+	| SCTP_INIT_MAX_ATTEMPTS EQUAL error { yyerror("number expected"); }
1327
+	| SCTP_INIT_MAX_TIMEO EQUAL NUMBER {
1328
+			IF_SCTP(sctp_default_cfg.init_max_timeo=$3);
1329
+	}
1330
+	| SCTP_INIT_MAX_TIMEO EQUAL error { yyerror("number expected"); }
1331
+	| SCTP_HBINTERVAL EQUAL NUMBER {
1332
+			IF_SCTP(sctp_default_cfg.hbinterval=$3);
1333
+	}
1334
+	| SCTP_HBINTERVAL EQUAL error { yyerror("number expected"); }
1335
+	| SCTP_PATHMAXRXT EQUAL NUMBER {
1336
+			IF_SCTP(sctp_default_cfg.pathmaxrxt=$3);
1337
+	}
1338
+	| SCTP_PATHMAXRXT EQUAL error { yyerror("number expected"); }
1339
+	| SCTP_SACK_DELAY EQUAL NUMBER {
1340
+			IF_SCTP(sctp_default_cfg.sack_delay=$3);
1341
+	}
1342
+	| SCTP_SACK_DELAY EQUAL error { yyerror("number expected"); }
1343
+	| SCTP_SACK_FREQ EQUAL NUMBER {
1344
+			IF_SCTP(sctp_default_cfg.sack_freq=$3);
1345
+	}
1346
+	| SCTP_SACK_FREQ EQUAL error { yyerror("number expected"); }
1347
+	| SCTP_MAX_BURST EQUAL NUMBER {
1348
+			IF_SCTP(sctp_default_cfg.max_burst=$3);
1349
+	}
1350
+	| SCTP_MAX_BURST EQUAL error { yyerror("number expected"); }
1255 1351
 	| SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
1256 1352
 	| SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
1257 1353
 	| 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 155
 void sctp_options_check()
55 156
 {
56 157
 #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) {
158
+	W_OPT_NSCTP(autoclose);
159
+	W_OPT_NSCTP(send_ttl);
160
+	W_OPT_NSCTP(send_retries);
161
+	W_OPT_NSCTP(assoc_tracking);
162
+	W_OPT_NSCTP(assoc_reuse);
163
+	W_OPT_NSCTP(max_assocs);
164
+#else /* USE_SCTP */
165
+	if (sctp_default_cfg.send_retries>MAX_SCTP_SEND_RETRIES) {
62 166
 		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;
167
+				sctp_default_cfg.send_retries, MAX_SCTP_SEND_RETRIES);
168
+		sctp_default_cfg.send_retries=MAX_SCTP_SEND_RETRIES;
65 169
 	}
66
-#endif
170
+#ifndef CONN_REUSE
171
+	if (sctp_default_cfg.assoc_tracking || sctp_default_cfg.assoc_reuse){
172
+		WARN("sctp_options: assoc_tracking and assoc_reuse support cannnot"
173
+				" be enabled (CONN_REUSE support not compiled-in)\n");
174
+		sctp_default_cfg.assoc_tracking=0;
175
+		sctp_default_cfg.assoc_reuse=0;
176
+	}
177
+#else /* CONN_REUSE */
178
+	if (sctp_default_cfg.assoc_reuse && sctp_default_cfg.assoc_tracking==0){
179
+		sctp_default_cfg.assoc_tracking=1;
180
+	}
181
+#endif /* CONN_REUSE */
182
+#endif /* USE_SCTP */
183
+}
184
+
185
+
186
+
187
+void sctp_options_get(struct cfg_group_sctp *s)
188
+{
189
+#ifdef USE_SCTP
190
+	*s=*(struct cfg_group_sctp*)sctp_cfg;
191
+#else
192
+	memset(s, 0, sizeof(*s));
193
+#endif /* USE_SCTP */
194
+}
195
+
196
+
197
+
198
+#ifdef USE_SCTP
199
+/** register sctp config into the configuration framework.
200
+ * @return 0 on success, -1 on error */
201
+int sctp_register_cfg()
202
+{
203
+	if (cfg_declare("sctp", sctp_cfg_def, &sctp_default_cfg, cfg_sizeof(sctp),
204
+				&sctp_cfg))
205
+		return -1;
206
+	if (sctp_cfg==0){
207
+		BUG("null sctp cfg");
208
+		return -1;
209
+	}
210
+	return 0;
211
+}
212
+
213
+
214
+
215
+#define SCTP_SET_SOCKOPT_DECLS \
216
+	int err; \
217
+	struct socket_info* si
218
+
219
+#define SCTP_SET_SOCKOPT_BODY(lev, opt_name, val, err_prefix) \
220
+	err=0; \
221
+	for (si=sctp_listen; si; si=si->next){ \
222
+		err+=(sctp_setsockopt(si->socket, (lev), (opt_name), (void*)(&(val)), \
223
+							sizeof((val)), (err_prefix))<0); \
224
+	} \
225
+	return -(err!=0)
226
+
227
+
228
+
229
+static int set_autoclose(void* cfg_h, str* gname, str* name, void** val)
230
+{
231
+#ifdef SCTP_AUTOCLOSE
232
+	int optval;
233
+	SCTP_SET_SOCKOPT_DECLS;
234
+	
235
+	optval=(int)(long)(*val);
236
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_AUTOCLOSE, optval,
237
+							"cfg: setting SCTP_AUTOCLOSE");
238
+#else
239
+	ERR("no SCTP_AUTOCLOSE support, please upgrade your sctp library\n");
240
+	return -1;
241
+#endif /* SCTP_AUTOCLOSE */
242
+}
243
+
244
+
245
+
246
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val)
247
+{
248
+	int optval;
249
+	
250
+	optval=(int)(long)(*val);
251
+#ifndef SCTP_CONN_REUSE
252
+	if (optval!=0){
253
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
254
+		return -1;
255
+	}
256
+#else /* SCTP_CONN_REUSE */
257
+	if (optval==0){
258
+		/* turn tracking off */
259
+		/* check if assoc_reuse is off */
260
+		if (cfg_get(sctp, cfg_h, assoc_reuse)!=0){
261
+			ERR("cannot turn sctp assoc_tracking off while assoc_reuse is"
262
+					" still on, please turn assoc_reuse off first\n");
263
+			return -1;
264
+		}
265
+		sctp_con_tracking_flush();
266
+	}else if (optval==1 && cfg_get(sctp, cfg_h, assoc_reuse)==0){
267
+		/* turning from off to on, make sure we flush the tracked list
268
+		   again, just incase the off flush was racing with a new connection*/
269
+		sctp_con_tracking_flush();
270
+	}
271
+#endif /* SCTP_CONN_REUSE */
272
+	return 0;
273
+}
274
+
275
+
276
+
277
+static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val)
278
+{
279
+	int optval;
280
+	
281
+	optval=(int)(long)(*val);
282
+#ifndef SCTP_CONN_REUSE
283
+	if (optval!=0){
284
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
285
+		return -1;
286
+	}
287
+#else /* SCTP_CONN_REUSE */
288
+	if (optval==1 && cfg_get(sctp, cfg_h, assoc_tracking)==0){
289
+		/* conn reuse on, but assoc_tracking off => not possible */
290
+		ERR("cannot turn sctp assoc_reuse on while assoc_tracking is"
291
+					" off, please turn assoc_tracking on first\n");
292
+		return -1;
293
+	}
294
+#endif /* SCTP_CONN_REUSE */
295
+	return 0;
296
+}
297
+
298
+
299
+
300
+static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val)
301
+{
302
+#ifdef SCTP_RTOINFO
303
+	struct sctp_rtoinfo rto;
304
+	SCTP_SET_SOCKOPT_DECLS;
305
+	
306
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
307
+		*val=(void*)(long)cfg_get(sctp, cfg_h, srto_initial);
308
+		return 0;
309
+	}
310
+	memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
311
+	rto.srto_assoc_id=0; /* all */
312
+	rto.srto_initial=(int)(long)(*val);
313
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
314
+							"cfg: setting SCTP_RTOINFO");
315
+#else
316
+	ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
317
+	return -1;
318
+#endif /* SCTP_RTOINFO */
319
+}
320
+
321
+
322
+
323
+static int set_srto_max(void* cfg_h, str* gname, str* name, void** val)
324
+{
325
+#ifdef SCTP_RTOINFO
326
+	struct sctp_rtoinfo rto;
327
+	SCTP_SET_SOCKOPT_DECLS;
328
+	
329
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
330
+		*val=(void*)(long)cfg_get(sctp, cfg_h, srto_max);
331
+		return 0;
332
+	}
333
+	memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
334
+	rto.srto_assoc_id=0; /* all */
335
+	rto.srto_max=(int)(long)(*val);
336
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
337
+							"cfg: setting SCTP_RTOINFO");
338
+#else
339
+	ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
340
+	return -1;
341
+#endif /* SCTP_RTOINFO */
67 342
 }
68 343
 
69 344
 
70 345
 
71
-void sctp_options_get(struct sctp_cfg_options *s)
346
+static int set_srto_min(void* cfg_h, str* gname, str* name, void** val)
72 347
 {
73
-	*s=sctp_options;
348
+#ifdef SCTP_RTOINFO
349
+	struct sctp_rtoinfo rto;
350
+	SCTP_SET_SOCKOPT_DECLS;
351
+	
352
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
353
+		*val=(void*)(long)cfg_get(sctp, cfg_h, srto_min);
354
+		return 0;
355
+	}
356
+	memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
357
+	rto.srto_assoc_id=0; /* all */
358
+	rto.srto_min=(int)(long)(*val);
359
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
360
+							"cfg: setting SCTP_RTOINFO");
361
+#else
362
+	ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
363
+	return -1;
364
+#endif /* SCTP_RTOINFO */
74 365
 }
366
+
367
+
368
+
369
+static int set_asocmaxrxt(void* cfg_h, str* gname, str* name, void** val)
370
+{
371
+#ifdef SCTP_ASSOCINFO
372
+	struct sctp_assocparams ap;
373
+	SCTP_SET_SOCKOPT_DECLS;
374
+	
375
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
376
+		*val=(void*)(long)cfg_get(sctp, cfg_h, asocmaxrxt);
377
+		return 0;
378
+	}
379
+	memset(&ap, 0, sizeof(ap)); /* zero everything we don't care about */
380
+	ap.sasoc_assoc_id=0; /* all */
381
+	ap.sasoc_asocmaxrxt=(int)(long)(*val);
382
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_ASSOCINFO, ap,
383
+							"cfg: setting SCTP_ASSOCINFO");
384
+#else
385
+	ERR("no SCTP_ASSOCINFO support, please upgrade your sctp library\n");
386
+	return -1;
387
+#endif /* SCTP_ASSOCINFO */
388
+}
389
+
390
+
391
+
392
+static int set_sinit_max_init_timeo(void* cfg_h, str* gname, str* name,
393
+									void** val)
394
+{
395
+#ifdef SCTP_INITMSG
396
+	struct sctp_initmsg im;
397
+	SCTP_SET_SOCKOPT_DECLS;
398
+	
399
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
400
+		*val=(void*)(long)cfg_get(sctp, cfg_h, init_max_timeo);
401
+		return 0;
402
+	}
403
+	memset(&im, 0, sizeof(im)); /* zero everything we don't care about */
404
+	im.sinit_max_init_timeo=(int)(long)(*val);
405
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_INITMSG, im,
406
+							"cfg: setting SCTP_INITMSG");
407
+#else
408
+	ERR("no SCTP_INITMSG support, please upgrade your sctp library\n");
409
+	return -1;
410
+#endif /* SCTP_INITMSG */
411
+}
412
+
413
+
414
+
415
+static int set_sinit_max_attempts(void* cfg_h, str* gname, str* name,
416
+									void** val)
417
+{
418
+#ifdef SCTP_INITMSG
419
+	struct sctp_initmsg im;
420
+	SCTP_SET_SOCKOPT_DECLS;
421
+	
422
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
423
+		*val=(void*)(long)cfg_get(sctp, cfg_h, init_max_attempts);
424
+		return 0;
425
+	}
426
+	memset(&im, 0, sizeof(im)); /* zero everything we don't care about */
427
+	im.sinit_max_attempts=(int)(long)(*val);
428
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_INITMSG, im,
429
+							"cfg: setting SCTP_INITMSG");
430
+#else
431
+	ERR("no SCTP_INITMSG support, please upgrade your sctp library\n");
432
+	return -1;
433
+#endif /* SCTP_INITMSG */
434
+}
435
+
436
+
437
+
438
+static int set_hbinterval(void* cfg_h, str* gname, str* name,
439
+									void** val)
440
+{
441
+#ifdef SCTP_PEER_ADDR_PARAMS
442
+	struct sctp_paddrparams pp;
443
+	SCTP_SET_SOCKOPT_DECLS;
444
+	
445
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
446
+		*val=(void*)(long)cfg_get(sctp, cfg_h, hbinterval);
447
+		return 0;
448
+	}
449
+	memset(&pp, 0, sizeof(pp)); /* zero everything we don't care about */
450
+	if ((int)(long)(*val)!=-1){
451
+		pp.spp_hbinterval=(int)(long)(*val);
452
+		pp.spp_flags=SPP_HB_ENABLE;
453
+	}else{
454
+		pp.spp_flags=SPP_HB_DISABLE;
455
+	}
456
+	err=0;
457
+	for (si=sctp_listen; si; si=si->next){
458
+		/* set the AF, needed on older linux kernels even for INADDR_ANY */
459
+		pp.spp_address.ss_family=si->address.af;
460
+		err+=(sctp_setsockopt(si->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
461
+								(void*)(&pp), sizeof(pp),
462
+								"cfg: setting SCTP_PEER_ADDR_PARAMS")<0);
463
+	}
464
+	return -(err!=0);
465
+#else
466
+	ERR("no SCTP_PEER_ADDR_PARAMS support, please upgrade your"
467
+			" sctp library\n");
468
+	return -1;
469
+#endif /* SCTP_PEER_ADDR_PARAMS */
470
+}
471
+
472
+
473
+
474
+static int set_pathmaxrxt(void* cfg_h, str* gname, str* name,
475
+									void** val)
476
+{
477
+#ifdef SCTP_PEER_ADDR_PARAMS
478
+	struct sctp_paddrparams pp;
479
+	SCTP_SET_SOCKOPT_DECLS;
480
+	
481
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
482
+		*val=(void*)(long)cfg_get(sctp, cfg_h, pathmaxrxt);
483
+		return 0;
484
+	}
485
+	memset(&pp, 0, sizeof(pp)); /* zero everything we don't care about */
486
+	pp.spp_pathmaxrxt=(int)(long)(*val);
487
+	err=0;
488
+	for (si=sctp_listen; si; si=si->next){
489
+		/* set the AF, needed on older linux kernels even for INADDR_ANY */
490
+		pp.spp_address.ss_family=si->address.af;
491
+		err+=(sctp_setsockopt(si->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
492
+								(void*)(&pp), sizeof(pp),
493
+								"cfg: setting SCTP_PEER_ADDR_PARAMS")<0);
494
+	}
495
+	return -(err!=0);
496
+#else
497
+	ERR("no SCTP_PEER_ADDR_PARAMS support, please upgrade your"
498
+			" sctp library\n");
499
+	return -1;
500
+#endif /* SCTP_PEER_ADDR_PARAMS */
501
+}
502
+
503
+
504
+
505
+static int set_sack_delay(void* cfg_h, str* gname, str* name, void** val)
506
+{
507
+#if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
508
+#ifdef SCTP_DELAYED_SACK
509
+	struct sctp_sack_info sa;
510
+#else /* old lib */
511
+	struct sctp_assoc_value sa;
512
+#endif /* SCTP_DELAYED_SACK */
513
+	SCTP_SET_SOCKOPT_DECLS;
514
+	
515
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
516
+		*val=(void*)(long)cfg_get(sctp, cfg_h, sack_delay);
517
+		return 0;
518
+	}
519
+	memset(&sa, 0, sizeof(sa)); /* zero everything we don't care about */
520
+#ifdef SCTP_DELAYED_SACK
521
+	sa.sack_delay=(int)(long)(*val);
522
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_SACK, sa,
523
+							"cfg: setting SCTP_DELAYED_SACK");
524
+#else /* old sctp lib version which uses SCTP_DELAYED_ACK_TIME */
525
+	sa.assoc_value=(int)(long)(*val);
526
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME, sa,
527
+							"cfg: setting SCTP_DELAYED_ACK_TIME");
528
+#endif /* SCTP_DELAYED_SACK */
529
+#else
530
+	ERR("no SCTP_DELAYED_SACK support, please upgrade your sctp library\n");
531
+	return -1;
532
+#endif /* SCTP_DELAYED_SACK | SCTP_DELAYED_ACK_TIME */
533
+}
534
+
535
+
536
+
537
+static int set_sack_freq(void* cfg_h, str* gname, str* name, void** val)
538
+{
539
+#ifdef SCTP_DELAYED_SACK
540
+	struct sctp_sack_info sa;
541
+	SCTP_SET_SOCKOPT_DECLS;
542
+	
543
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
544
+		*val=(void*)(long)cfg_get(sctp, cfg_h, sack_freq);
545
+		return 0;
546
+	}
547
+	memset(&sa, 0, sizeof(sa)); /* zero everything we don't care about */
548
+	sa.sack_freq=(int)(long)(*val);
549
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_SACK, sa,
550
+							"cfg: setting SCTP_DELAYED_SACK");
551
+#else
552
+	ERR("no SCTP_DELAYED_SACK support, please upgrade your sctp library\n");
553
+	return -1;
554
+#endif /* SCTP_DELAYED_SACK */
555
+}
556
+
557
+
558
+
559
+static int set_max_burst(void* cfg_h, str* gname, str* name, void** val)
560
+{
561
+#ifdef SCTP_MAX_BURST
562
+	struct sctp_assoc_value av;
563
+	SCTP_SET_SOCKOPT_DECLS;
564
+	
565
+	if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
566
+		*val=(void*)(long)cfg_get(sctp, cfg_h, max_burst);
567
+		return 0;
568
+	}
569
+	memset(&av, 0, sizeof(av)); /* zero everything we don't care about */
570
+	av.assoc_value=(int)(long)(*val);
571
+	SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_MAX_BURST, av,
572
+							"cfg: setting SCTP_MAX_BURST");
573
+#else
574
+	ERR("no SCTP_MAX_BURST support, please upgrade your sctp library\n");
575
+	return -1;
576
+#endif /* SCTP_MAX_BURST */
577
+}
578
+
579
+#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 189
 
186 190
 
187 191
 
192
+/** set a socket option (wrapper over setsockopt).
193
+  * @param err_prefix - if 0 no error message is printed on failure, if !=0
194
+  *                     it will be prepended to the error message.
195
+  * @return 0 on success, -1 on error */
196
+int sctp_setsockopt(int s, int level, int optname, 
197
+					void* optval, socklen_t optlen, char* err_prefix)
198
+{
199
+	if (setsockopt(s, level, optname, optval, optlen) ==-1){
200
+		if (err_prefix)
201
+			ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
202
+		return -1;
203
+	}
204
+	return 0;
205
+}
206
+
207
+
208
+
209
+/** get a socket option (wrapper over getsockopt).
210
+  * @param err_prefix - if 0 no error message is printed on failure, if !=0
211
+  *                     it will be prepended to the error message.
212
+  * @return 0 on success, -1 on error */
213
+int sctp_getsockopt(int s, int level, int optname, 
214
+					void* optval, socklen_t* optlen, char* err_prefix)
215
+{
216
+	if (getsockopt(s, level, optname, optval, optlen) ==-1){
217
+		if (err_prefix)
218
+			ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
219
+		return -1;
220
+	}
221
+	return 0;
222
+}
223
+
224
+
225
+
226
+/** get the os defaults for cfg options with os correspondents.
227
+ *  @param s - intialized sctp socket
228
+ *  @param cfg - filled with the os defaults
229
+ *  @return -1 on error, 0 on success
230
+ */
231
+int sctp_get_os_defaults(struct cfg_group_sctp* cfg)
232
+{
233
+	int optval;
234
+	socklen_t optlen;
235
+	int s;
236
+#ifdef SCTP_RTOINFO
237
+	struct sctp_rtoinfo rto;
238
+#endif /* SCTP_RTOINFO */
239
+#ifdef SCTP_ASSOCINFO
240
+	struct sctp_assocparams ap;
241
+#endif /* SCTP_ASSOCINFO */
242
+#ifdef SCTP_INITMSG
243
+	struct sctp_initmsg im;
244
+#endif /* SCTP_INITMSG */
245
+#ifdef SCTP_PEER_ADDR_PARAMS
246
+	struct sctp_paddrparams pp;
247
+#endif /* SCTP_PEER_ADDR_PARAMS */
248
+#ifdef SCTP_DELAYED_SACK
249
+	struct sctp_sack_info sa;
250
+#elif defined SCTP_DELAYED_ACK_TIME /* old version */
251
+	struct sctp_assoc_value sa;
252
+#endif /* SCTP_DELAYED_SACK */
253
+#ifdef SCTP_MAX_BURST
254
+	struct sctp_assoc_value av;
255
+#endif /* SCTP_MAX_BURST */
256
+	
257
+	s = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
258
+	if (s==-1)
259
+		return -1;
260
+	
261
+	/* SO_RCVBUF */
262
+	optlen=sizeof(int);
263
+	if (sctp_getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&optval,
264
+							&optlen, "SO_RCVBUF")==0){
265
+		/* success => hack to set the "default" values*/
266
+		#ifdef __OS_linux
267
+			optval/=2; /* in linux getsockopt() returns 2*set_value */
268
+		#endif
269
+		cfg->so_rcvbuf=optval;
270
+	}
271
+	/* SO_SNDBUF */
272
+	optlen=sizeof(int);
273
+	if (sctp_getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&optval,
274
+							&optlen, "SO_SNDBUF")==0){
275
+		/* success => hack to set the "default" values*/
276
+		#ifdef __OS_linux
277
+			optval/=2; /* in linux getsockopt() returns 2*set_value */
278
+		#endif
279
+		cfg->so_sndbuf=optval;
280
+	}
281
+	/* SCTP_RTOINFO -> srto_initial, srto_min, srto_max */
282
+#ifdef SCTP_RTOINFO
283
+	optlen=sizeof(rto);
284
+	rto.srto_assoc_id=0;
285
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
286
+							&optlen, "SCTP_RTOINFO")==0){
287
+		/* success => hack to set the "default" values*/
288
+		cfg->srto_initial=rto.srto_initial;
289
+		cfg->srto_min=rto.srto_min;
290
+		cfg->srto_max=rto.srto_max;
291
+	}
292
+#endif /* SCTP_RTOINFO */
293
+#ifdef SCTP_ASSOCINFO
294
+	optlen=sizeof(ap);
295
+	ap.sasoc_assoc_id=0;
296
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_ASSOCINFO, (void*)&ap,
297
+							&optlen, "SCTP_ASSOCINFO")==0){
298
+		/* success => hack to set the "default" values*/
299
+		cfg->asocmaxrxt=ap.sasoc_asocmaxrxt;
300
+	}
301
+#endif /* SCTP_ASSOCINFO */
302
+#ifdef SCTP_INITMSG
303
+	optlen=sizeof(im);
304
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, (void*)&im,
305
+							&optlen, "SCTP_INITMSG")==0){
306
+		/* success => hack to set the "default" values*/
307
+		cfg->init_max_attempts=im.sinit_max_attempts;
308
+		cfg->init_max_timeo=im.sinit_max_init_timeo;
309
+	}
310
+#endif /* SCTP_INITMSG */
311
+#ifdef SCTP_PEER_ADDR_PARAMS
312
+	optlen=sizeof(pp);
313
+	memset(&pp, 0, sizeof(pp)); /* get defaults */
314
+	/* set the AF, needed on older linux kernels even for INADDR_ANY */
315
+	pp.spp_address.ss_family=AF_INET;
316
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, (void*)&pp,
317
+							&optlen, "SCTP_PEER_ADDR_PARAMS")==0){
318
+		/* success => hack to set the "default" values*/
319
+		cfg->hbinterval=pp.spp_hbinterval;
320
+		cfg->pathmaxrxt=pp.spp_pathmaxrxt;
321
+	}
322
+#endif /* SCTP_PEER_ADDR_PARAMS */
323
+#if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
324
+	optlen=sizeof(sa);
325
+	memset(&sa, 0, sizeof(sa));
326
+#ifdef SCTP_DELAYED_SACK
327
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_SACK, (void*)&sa,
328
+							&optlen, "SCTP_DELAYED_SACK")==0){
329
+		/* success => hack to set the "default" values*/
330
+		cfg->sack_delay=sa.sack_delay;
331
+		cfg->sack_freq=sa.sack_freq;
332
+	}
333
+#else /* old sctp lib version which uses SCTP_DELAYED_ACK_TIME */
334
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME, (void*)&sa,
335
+							&optlen, "SCTP_DELAYED_ACK_TIME")==0){
336
+		/* success => hack to set the "default" values*/
337
+		cfg->sack_delay=sa.assoc_value;
338
+		cfg->sack_freq=0; /* unknown */
339
+	}
340
+#endif /* SCTP_DELAYED_SACK */
341
+#endif /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
342
+#ifdef SCTP_MAX_BURST
343
+	optlen=sizeof(av);
344
+	av.assoc_id=0;
345
+	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_MAX_BURST, (void*)&av,
346
+							&optlen, "SCTP_MAX_BURST")==0){
347
+		/* success => hack to set the "default" values*/
348
+		cfg->max_burst=av.assoc_value;
349
+	}
350
+#endif /* SCTP_MAX_BURST */
351
+	
352
+	close(s);
353
+	return 0;
354
+}
355
+
356
+
357
+
188 358
 /* set common (for one to many and one to one) sctp socket options
189 359
    tries to ignore non-critical errors (it will only log them), for
190 360
    improved portability (for example older linux kernel version support
191 361
    only a limited number of sctp socket options)
192 362
    returns 0 on success, -1 on error
193 363
    WARNING: please keep it sync'ed w/ sctp_check_compiled_sockopts() */
194
-static int sctp_init_sock_opt_common(int s)
364
+static int sctp_init_sock_opt_common(int s, int af)
195 365
 {
196
-	struct sctp_event_subscribe es;
197 366
 	int optval;
367
+	int pd_point;
368
+	int saved_errno;
198 369
 	socklen_t optlen;
199 370
 	int sctp_err;
371
+#ifdef SCTP_RTOINFO
372
+	struct sctp_rtoinfo rto;
373
+#endif /* SCTP_RTOINFO */
374
+#ifdef SCTP_ASSOCINFO
375
+	struct sctp_assocparams ap;
376
+#endif /* SCTP_ASSOCINFO */
377
+#ifdef SCTP_INITMSG
378
+	struct sctp_initmsg im;
379
+#endif /* SCTP_INITMSG */
380
+#ifdef SCTP_PEER_ADDR_PARAMS
381
+	struct sctp_paddrparams pp;
382
+#endif /* SCTP_PEER_ADDR_PARAMS */
383
+#ifdef SCTP_DELAYED_SACK
384
+	struct sctp_sack_info sa;
385
+#elif defined SCTP_DELAYED_ACK_TIME /* old version */
386
+	struct sctp_assoc_value sa;
387
+#endif /* SCTP_DELAYED_SACK */
388
+#ifdef SCTP_MAX_BURST
389
+	struct sctp_assoc_value av;
390
+#endif /* SCTP_MAX_BURST */
391
+	
392
+#ifdef __OS_linux
393
+	union {
394
+		struct sctp_event_subscribe s;
395
+		char padding[sizeof(struct sctp_event_subscribe)+sizeof(__u8)];
396
+	} es;
397
+#else
398
+	struct sctp_event_subscribe es;
399
+#endif
400
+	struct sctp_event_subscribe* ev_s;
200 401
 	
201 402
 	sctp_err=0;
403
+#ifdef __OS_linux
404
+	ev_s=&es.s;
405
+#else
406
+	ev_s=&es;
407
+#endif
202 408
 	/* set tos */
203 409
 	optval = tos;
204 410
 	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 414
 	}
209 415
 	
210 416
 	/* set receive buffer: SO_RCVBUF*/
211
-	if (sctp_options.sctp_so_rcvbuf){
212
-		optval=sctp_options.sctp_so_rcvbuf;
417
+	if (cfg_get(sctp, sctp_cfg, so_rcvbuf)){
418
+		optval=cfg_get(sctp, sctp_cfg, so_rcvbuf);
213 419
 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
214 420
 					(void*)&optval, sizeof(optval)) ==-1){
215 421
 			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
... ...
@@ -219,8 +425,8 @@ static int sctp_init_sock_opt_common(int s)
219 425
 	}
220 426
 	
221 427
 	/* set send buffer: SO_SNDBUF */
222
-	if (sctp_options.sctp_so_sndbuf){
223
-		optval=sctp_options.sctp_so_sndbuf;
428
+	if (cfg_get(sctp, sctp_cfg, so_sndbuf)){
429
+		optval=cfg_get(sctp, sctp_cfg, so_sndbuf);
224 430
 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
225 431
 					(void*)&optval, sizeof(optval)) ==-1){
226 432
 			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
... ...
@@ -267,13 +473,34 @@ static int sctp_init_sock_opt_common(int s)
267 473
 		/* try to continue */
268 474
 		optval=0;
269 475
 	}
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: "
476
+#ifdef __OS_linux
477
+	optval/=2; /* in linux getsockopt() returns twice the set value */
478
+#endif
479
+	pd_point=optval;
480
+	saved_errno=0;
481
+	while(pd_point &&
482
+			setsockopt(s, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
483
+					(void*)&pd_point, sizeof(pd_point)) ==-1){
484
+		if (!saved_errno)
485
+			saved_errno=errno;
486
+		pd_point--;
487
+	}
488
+	
489
+	if (pd_point!=optval){
490
+		if (pd_point==0){
491
+			/* all attempts failed */
492
+			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
273 493
 						"SCTP_PARTIAL_DELIVERY_POINT (%d): %s\n",
274 494
 						optval, strerror(errno));
275
-		sctp_err++;
276
-		/* try to continue */
495
+			sctp_err++;
496
+			/* try to continue */
497
+		}else{
498
+			/* success but to a lower value (might not be disabled) */
499
+			LOG(L_WARN, "setsockopt SCTP_PARTIAL_DELIVERY_POINT set to %d, but"
500
+				" the socket rcvbuf is %d (higher values fail with"
501
+				" \"%s\" [%d])\n",
502
+				pd_point, optval, strerror(saved_errno), saved_errno);
503
+		}
277 504
 	}
278 505
 #else
279 506
 #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 536
 	
310 537
 	/* set autoclose */
311 538
 #ifdef SCTP_AUTOCLOSE
312
-	optval=sctp_options.sctp_autoclose;
539
+	optval=cfg_get(sctp, sctp_cfg, autoclose);
313 540
 	if (setsockopt(s, IPPROTO_SCTP, SCTP_AUTOCLOSE,
314 541
 					(void*)&optval, sizeof(optval)) ==-1){
315 542
 		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
... ...
@@ -322,31 +549,171 @@ static int sctp_init_sock_opt_common(int s)
322 549
 #else
323 550
 #error SCTP_AUTOCLOSE not supported, please upgrade your sctp library
324 551
 #endif /* SCTP_AUTOCLOSE */
552
+	/* set rtoinfo options: srto_initial, srto_min, srto_max */
553
+#ifdef SCTP_RTOINFO
554
+	memset(&rto, 0, sizeof(rto));
555
+	rto.srto_initial=cfg_get(sctp, sctp_cfg, srto_initial);
556
+	rto.srto_min=cfg_get(sctp, sctp_cfg, srto_min);
557
+	rto.srto_max=cfg_get(sctp, sctp_cfg, srto_max);
558
+	if (rto.srto_initial || rto.srto_min || rto.srto_max){
559
+		/* if at least one is non-null => we have to set it */
560
+		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
561
+							sizeof(rto), "setsockopt: SCTP_RTOINFO")!=0){
562
+			sctp_err++;
563
+			/* non critical, try to continue */
564
+		}
565
+	}
566