Browse code

sctp: new module for SCTP transport

- moved the sctp specific code from core to a module to make it easy to
enable/disable sctp by loading/not loading the module instead of
recompiling

Daniel-Constantin Mierla authored on 25/05/2013 07:33:39
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,2920 +0,0 @@
1
-/* 
2
- * $Id$
3
- * 
4
- * Copyright (C) 2008 iptelorg GmbH
5
- *
6
- * Permission to use, copy, modify, and distribute this software for any
7
- * purpose with or without fee is hereby granted, provided that the above
8
- * copyright notice and this permission notice appear in all copies.
9
- *
10
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
- */
18
-/* 
19
- * sctp one to many 
20
- */
21
-/*
22
- * History:
23
- * --------
24
- *  2008-08-07  initial version (andrei)
25
- *  2009-02-27  blacklist support (andrei)
26
- *  2009-04-28  sctp stats & events macros (andrei)
27
- */
28
-
29
-/*!
30
- * \file
31
- * \brief SIP-router core :: 
32
- * \ingroup core
33
- * Module: \ref core
34
- */
35
-
36
-#ifdef USE_SCTP
37
-
38
-#include <stdlib.h>
39
-#include <string.h>
40
-#include <sys/types.h>
41
-#include <sys/socket.h>
42
-#include <netinet/in.h>
43
-#include <netinet/in_systm.h>
44
-#include <netinet/ip.h>
45
-#include <netinet/sctp.h>
46
-#include <errno.h>
47
-#include <arpa/inet.h>
48
-#include <unistd.h>
49
-#include <fcntl.h>
50
-
51
-
52
-#include "sctp_sockopts.h"
53
-#include "sctp_server.h"
54
-#include "sctp_options.h"
55
-#include "globals.h"
56
-#include "config.h"
57
-#include "dprint.h"
58
-#include "receive.h"
59
-#include "mem/mem.h"
60
-#include "ip_addr.h"
61
-#include "cfg/cfg_struct.h"
62
-#ifdef USE_DST_BLACKLIST
63
-#include "dst_blacklist.h"
64
-#endif /* USE_DST_BLACKLIST */
65
-#include "timer_ticks.h"
66
-#include "clist.h"
67
-#include "error.h"
68
-#include "timer.h"
69
-#include "sctp_stats.h"
70
-#include "sctp_ev.h"
71
-
72
-
73
-
74
-static atomic_t* sctp_conn_no;
75
-
76
-
77
-#define ABORT_REASON_MAX_ASSOCS \
78
-	"Maximum configured number of open associations exceeded"
79
-
80
-/* check if the underlying OS supports sctp
81
-   returns 0 if yes, -1 on error */
82
-int sctp_check_support()
83
-{
84
-	int s;
85
-	char buf[256];
86
-	
87
-	s = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
88
-	if (s!=-1){
89
-		close(s);
90
-		if (sctp_check_compiled_sockopts(buf, sizeof(buf))!=0){
91
-			LOG(L_WARN, "WARNING: sctp: your ser version was compiled"
92
-						" without support for the following sctp options: %s"
93
-						", which might cause unforseen problems \n", buf);
94
-			LOG(L_WARN, "WARNING: sctp: please consider recompiling ser with"
95
-						" an upgraded sctp library version\n");
96
-		}
97
-		return 0;
98
-	}
99
-	return -1;
100
-}
101
-
102
-
103
-
104
-/* append a token to a buffer (uses space between tokens) */
105
-inline static void append_tok2buf(char* buf, int blen, char* tok)
106
-{
107
-	char* p;
108
-	char* end;
109
-	int len;
110
-	
111
-	if (buf && blen){
112
-		end=buf+blen;
113
-		p=memchr(buf, 0, blen);
114
-		if (p==0) goto error;
115
-		if (p!=buf && p<(end-1)){
116
-			*p=' ';
117
-			p++;
118
-		}
119
-		len=MIN_int(strlen(tok), end-1-p);
120
-		memcpy(p, tok, len);
121
-		p[len]=0;
122
-	}
123
-error:
124
-	return;
125
-}
126
-
127
-
128
-
129
-/* check if support fot all the needed sockopts  was compiled;
130
-   an ascii list of the unsuported options is returned in buf
131
-   returns 0 on success and  -number of unsuported options on failure
132
-   (<0 on failure)
133
-*/
134
-int sctp_check_compiled_sockopts(char* buf, int size)
135
-{
136
-	int err;
137
-
138
-	err=0;
139
-	if (buf && (size>0)) *buf=0; /* "" */
140
-#ifndef SCTP_FRAGMENT_INTERLEAVE
141
-	err++;
142
-	append_tok2buf(buf, size, "SCTP_FRAGMENT_INTERLEAVE");
143
-#endif
144
-#ifndef SCTP_PARTIAL_DELIVERY_POINT
145
-	err++;
146
-	append_tok2buf(buf, size, "SCTP_PARTIAL_DELIVERY_POINT");
147
-#endif
148
-#ifndef SCTP_NODELAY
149
-	err++;
150
-	append_tok2buf(buf, size, "SCTP_NODELAY");
151
-#endif
152
-#ifndef SCTP_DISABLE_FRAGMENTS
153
-	err++;
154
-	append_tok2buf(buf, size, "SCTP_DISABLE_FRAGMENTS");
155
-#endif
156
-#ifndef SCTP_AUTOCLOSE
157
-	err++;
158
-	append_tok2buf(buf, size, "SCTP_AUTOCLOSE");
159
-#endif
160
-#ifndef SCTP_EVENTS
161
-	err++;
162
-	append_tok2buf(buf, size, "SCTP_EVENTS");
163
-#endif
164
-	
165
-	return -err;
166
-}
167
-
168
-
169
-
170
-/* init all the sockaddr_union members of the socket_info struct
171
-   returns 0 on success and -1 on error */
172
-inline static int sctp_init_su(struct socket_info* sock_info)
173
-{
174
-	union sockaddr_union* addr;
175
-	struct addr_info* ai;
176
-	
177
-	addr=&sock_info->su;
178
-	if (init_su(addr, &sock_info->address, sock_info->port_no)<0){
179
-		LOG(L_ERR, "ERROR: sctp_init_su: could not init sockaddr_union for"
180
-					"primary sctp address %.*s:%d\n",
181
-					sock_info->address_str.len, sock_info->address_str.s,
182
-					sock_info->port_no );
183
-		goto error;
184
-	}
185
-	for (ai=sock_info->addr_info_lst; ai; ai=ai->next)
186
-		if (init_su(&ai->su, &ai->address, sock_info->port_no)<0){
187
-			LOG(L_ERR, "ERROR: sctp_init_su: could not init"
188
-					"backup sctp sockaddr_union for %.*s:%d\n",
189
-					ai->address_str.len, ai->address_str.s,
190
-					sock_info->port_no );
191
-			goto error;
192
-		}
193
-	return 0;
194
-error:
195
-	return -1;
196
-}
197
-
198
-
199
-
200
-/** set a socket option (wrapper over setsockopt).
201
-  * @param err_prefix - if 0 no error message is printed on failure, if !=0
202
-  *                     it will be prepended to the error message.
203
-  * @return 0 on success, -1 on error */
204
-int sctp_setsockopt(int s, int level, int optname, 
205
-					void* optval, socklen_t optlen, char* err_prefix)
206
-{
207
-	if (setsockopt(s, level, optname, optval, optlen) ==-1){
208
-		if (err_prefix)
209
-			ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
210
-		return -1;
211
-	}
212
-	return 0;
213
-}
214
-
215
-
216
-
217
-/** get a socket option (wrapper over getsockopt).
218
-  * @param err_prefix - if 0 no error message is printed on failure, if !=0
219
-  *                     it will be prepended to the error message.
220
-  * @return 0 on success, -1 on error */
221
-int sctp_getsockopt(int s, int level, int optname, 
222
-					void* optval, socklen_t* optlen, char* err_prefix)
223
-{
224
-	if (getsockopt(s, level, optname, optval, optlen) ==-1){
225
-		if (err_prefix)
226
-			ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
227
-		return -1;
228
-	}
229
-	return 0;
230
-}
231
-
232
-
233
-
234
-/** get the os defaults for cfg options with os correspondents.
235
- *  @param cfg - filled with the os defaults
236
- *  @return -1 on error, 0 on success
237
- */
238
-int sctp_get_os_defaults(struct cfg_group_sctp* cfg)
239
-{
240
-	int s;
241
-	int ret;
242
-	
243
-	s = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
244
-	if (s==-1)
245
-		return -1;
246
-	ret=sctp_get_cfg_from_sock(s, cfg);
247
-	close(s);
248
-	return ret;
249
-}
250
-
251
-
252
-
253
-/** get the os cfg options from a specific socket.
254
- *  @param s - intialized sctp socket
255
- *  @param cfg - filled with the os defaults
256
- *  @return -1 on error, 0 on success
257
- */
258
-int sctp_get_cfg_from_sock(int s, struct cfg_group_sctp* cfg)
259
-{
260
-	int optval;
261
-	socklen_t optlen;
262
-#ifdef SCTP_RTOINFO
263
-	struct sctp_rtoinfo rto;
264
-#endif /* SCTP_RTOINFO */
265
-#ifdef SCTP_ASSOCINFO
266
-	struct sctp_assocparams ap;
267
-#endif /* SCTP_ASSOCINFO */
268
-#ifdef SCTP_INITMSG
269
-	struct sctp_initmsg im;
270
-#endif /* SCTP_INITMSG */
271
-#ifdef SCTP_PEER_ADDR_PARAMS
272
-	struct sctp_paddrparams pp;
273
-#endif /* SCTP_PEER_ADDR_PARAMS */
274
-#ifdef	SCTP_DELAYED_SACK
275
-	struct sctp_sack_info sack_info;
276
-#endif	/* SCTP_DELAYED_SACK */
277
-#ifdef	SCTP_DELAYED_ACK_TIME
278
-	struct sctp_assoc_value sack_val; /* old version */
279
-#endif /* SCTP_DELAYED_ACK_TIME */
280
-#ifdef SCTP_MAX_BURST
281
-	struct sctp_assoc_value av;
282
-#endif /* SCTP_MAX_BURST */
283
-	
284
-	/* SO_RCVBUF */
285
-	optlen=sizeof(int);
286
-	if (sctp_getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&optval,
287
-							&optlen, "SO_RCVBUF")==0){
288
-		/* success => hack to set the "default" values*/
289
-		#ifdef __OS_linux
290
-			optval/=2; /* in linux getsockopt() returns 2*set_value */
291
-		#endif
292
-		cfg->so_rcvbuf=optval;
293
-	}
294
-	/* SO_SNDBUF */
295
-	optlen=sizeof(int);
296
-	if (sctp_getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&optval,
297
-							&optlen, "SO_SNDBUF")==0){
298
-		/* success => hack to set the "default" values*/
299
-		#ifdef __OS_linux
300
-			optval/=2; /* in linux getsockopt() returns 2*set_value */
301
-		#endif
302
-		cfg->so_sndbuf=optval;
303
-	}
304
-	/* SCTP_AUTOCLOSE */
305
-#ifdef SCTP_AUTOCLOSE
306
-	optlen=sizeof(int);
307
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_AUTOCLOSE, (void*)&optval,
308
-							&optlen, "SCTP_AUTOCLOSE")==0){
309
-		cfg->autoclose=optval;
310
-	}
311
-#endif /* SCTP_AUTOCLOSE */
312
-	/* SCTP_RTOINFO -> srto_initial, srto_min, srto_max */
313
-#ifdef SCTP_RTOINFO
314
-	optlen=sizeof(rto);
315
-	rto.srto_assoc_id=0;
316
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
317
-							&optlen, "SCTP_RTOINFO")==0){
318
-		/* success => hack to set the "default" values*/
319
-		cfg->srto_initial=rto.srto_initial;
320
-		cfg->srto_min=rto.srto_min;
321
-		cfg->srto_max=rto.srto_max;
322
-	}
323
-#endif /* SCTP_RTOINFO */
324
-#ifdef SCTP_ASSOCINFO
325
-	optlen=sizeof(ap);
326
-	ap.sasoc_assoc_id=0;
327
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_ASSOCINFO, (void*)&ap,
328
-							&optlen, "SCTP_ASSOCINFO")==0){
329
-		/* success => hack to set the "default" values*/
330
-		cfg->asocmaxrxt=ap.sasoc_asocmaxrxt;
331
-	}
332
-#endif /* SCTP_ASSOCINFO */
333
-#ifdef SCTP_INITMSG
334
-	optlen=sizeof(im);
335
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, (void*)&im,
336
-							&optlen, "SCTP_INITMSG")==0){
337
-		/* success => hack to set the "default" values*/
338
-		cfg->init_max_attempts=im.sinit_max_attempts;
339
-		cfg->init_max_timeo=im.sinit_max_init_timeo;
340
-	}
341
-#endif /* SCTP_INITMSG */
342
-#ifdef SCTP_PEER_ADDR_PARAMS
343
-	optlen=sizeof(pp);
344
-	memset(&pp, 0, sizeof(pp)); /* get defaults */
345
-	/* set the AF, needed on older linux kernels even for INADDR_ANY */
346
-	pp.spp_address.ss_family=AF_INET;
347
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, (void*)&pp,
348
-							&optlen, "SCTP_PEER_ADDR_PARAMS")==0){
349
-		/* success => hack to set the "default" values*/
350
-		cfg->hbinterval=pp.spp_hbinterval;
351
-		cfg->pathmaxrxt=pp.spp_pathmaxrxt;
352
-	}
353
-#endif /* SCTP_PEER_ADDR_PARAMS */
354
-#if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
355
-#ifdef SCTP_DELAYED_SACK
356
-	optlen=sizeof(sack_info);
357
-	memset(&sack_info, 0, sizeof(sack_info));
358
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_SACK, (void*)&sack_info,
359
-							&optlen, 0)==0){
360
-		/* success => hack to set the "default" values*/
361
-		cfg->sack_delay=sack_info.sack_delay;
362
-		cfg->sack_freq=sack_info.sack_freq;
363
-	}else
364
-#endif /* SCTP_DELAYED_SACK */
365
-	{
366
-#ifdef	SCTP_DELAYED_ACK_TIME
367
-		optlen=sizeof(sack_val);
368
-		memset(&sack_val, 0, sizeof(sack_val));
369
-		/* if no SCTP_DELAYED_SACK supported by the sctp lib, or setting it
370
-		   failed (not supported by the kernel) try using the obsolete
371
-		   SCTP_DELAYED_ACK_TIME method */
372
-		if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME,
373
-								(void*)&sack_val, &optlen, 
374
-								"SCTP_DELAYED_ACK_TIME")==0){
375
-			/* success => hack to set the "default" values*/
376
-			cfg->sack_delay=sack_val.assoc_value;
377
-			cfg->sack_freq=0; /* unknown */
378
-		}
379
-#else	/* SCTP_DELAYED_ACK_TIME */
380
-		/* no SCTP_DELAYED_ACK_TIME support and SCTP_DELAYED_SACK failed
381
-		   => error */
382
-		ERR("cfg: SCTP_DELAYED_SACK: %s [%d]\n", strerror(errno), errno);
383
-#endif /* SCTP_DELAYED_ACK_TIME */
384
-	}
385
-#endif /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
386
-#ifdef SCTP_MAX_BURST
387
-	optlen=sizeof(av);
388
-	av.assoc_id=0;
389
-	if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_MAX_BURST, (void*)&av,
390
-							&optlen, "SCTP_MAX_BURST")==0){
391
-		/* success => hack to set the "default" values*/
392
-		cfg->max_burst=av.assoc_value;
393
-	}
394
-#endif /* SCTP_MAX_BURST */
395
-	
396
-	return 0;
397
-}
398
-
399
-
400
-
401
-/* set common (for one to many and one to one) sctp socket options
402
-   tries to ignore non-critical errors (it will only log them), for
403
-   improved portability (for example older linux kernel version support
404
-   only a limited number of sctp socket options)
405
-   returns 0 on success, -1 on error
406
-   WARNING: please keep it sync'ed w/ sctp_check_compiled_sockopts() */
407
-static int sctp_init_sock_opt_common(int s, int af)
408
-{
409
-	int optval;
410
-	int pd_point;
411
-	int saved_errno;
412
-	socklen_t optlen;
413
-	int sctp_err;
414
-#ifdef SCTP_RTOINFO
415
-	struct sctp_rtoinfo rto;
416
-#endif /* SCTP_RTOINFO */
417
-#ifdef SCTP_ASSOCINFO
418
-	struct sctp_assocparams ap;
419
-#endif /* SCTP_ASSOCINFO */
420
-#ifdef SCTP_INITMSG
421
-	struct sctp_initmsg im;
422
-#endif /* SCTP_INITMSG */
423
-#ifdef SCTP_PEER_ADDR_PARAMS
424
-	struct sctp_paddrparams pp;
425
-#endif /* SCTP_PEER_ADDR_PARAMS */
426
-#ifdef SCTP_DELAYED_SACK
427
-	struct sctp_sack_info sack_info;
428
-#endif	/* SCTP_DELAYED_SACK */
429
-#ifdef	SCTP_DELAYED_ACK_TIME
430
-	struct sctp_assoc_value sack_val;
431
-#endif /* defined SCTP_DELAYED_ACK_TIME */
432
-#ifdef SCTP_MAX_BURST
433
-	struct sctp_assoc_value av;
434
-#endif /* SCTP_MAX_BURST */
435
-	
436
-#ifdef __OS_linux
437
-	union {
438
-		struct sctp_event_subscribe s;
439
-		char padding[sizeof(struct sctp_event_subscribe)+sizeof(__u8)];
440
-	} es;
441
-#else
442
-	struct sctp_event_subscribe es;
443
-#endif
444
-	struct sctp_event_subscribe* ev_s;
445
-	
446
-	sctp_err=0;
447
-#ifdef __OS_linux
448
-	ev_s=&es.s;
449
-#else
450
-	ev_s=&es;
451
-#endif
452
-	/* set tos */
453
-	optval = tos;
454
-	if(af==AF_INET){
455
-		if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval,
456
-					sizeof(optval)) ==-1){
457
-			LM_WARN("sctp_init_sock_opt_common: setsockopt tos: %s\n",
458
-					strerror(errno));
459
-			/* continue since this is not critical */
460
-		}
461
-	} else if(af==AF_INET6){
462
-		if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS,
463
-					(void*)&optval, sizeof(optval)) ==-1) {
464
-			LM_WARN("sctp_init_sock_opt_common: setsockopt v6 tos: %s\n",
465
-					strerror(errno));
466
-			/* continue since this is not critical */
467
-		}
468
-	}
469
-	
470
-	/* set receive buffer: SO_RCVBUF*/
471
-	if (cfg_get(sctp, sctp_cfg, so_rcvbuf)){
472
-		optval=cfg_get(sctp, sctp_cfg, so_rcvbuf);
473
-		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
474
-					(void*)&optval, sizeof(optval)) ==-1){
475
-			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
476
-						" SO_RCVBUF (%d): %s\n", optval, strerror(errno));
477
-			/* continue, non-critical */
478
-		}
479
-	}
480
-	
481
-	/* set send buffer: SO_SNDBUF */
482
-	if (cfg_get(sctp, sctp_cfg, so_sndbuf)){
483
-		optval=cfg_get(sctp, sctp_cfg, so_sndbuf);
484
-		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
485
-					(void*)&optval, sizeof(optval)) ==-1){
486
-			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
487
-						" SO_SNDBUF (%d): %s\n", optval, strerror(errno));
488
-			/* continue, non-critical */
489
-		}
490
-	}
491
-	
492
-	/* set reuseaddr */
493
-	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
494
-						(void*)&optval, sizeof(optval))==-1){
495
-			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
496
-						" SO_REUSEADDR (%d): %s\n", optval, strerror(errno));
497
-			/* continue, non-critical */
498
-	}
499
-
500
-	
501
-	/* disable fragments interleave (SCTP_FRAGMENT_INTERLEAVE) --
502
-	 * we don't want partial delivery, so fragment interleave must be off too
503
-	 */
504
-#ifdef SCTP_FRAGMENT_INTERLEAVE
505
-	optval=0;
506
-	if (setsockopt(s, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE ,
507
-					(void*)&optval, sizeof(optval)) ==-1){
508
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
509
-					"SCTP_FRAGMENT_INTERLEAVE: %s\n", strerror(errno));
510
-		sctp_err++;
511
-		/* try to continue */
512
-	}
513
-#else
514
-#warning no sctp lib support for SCTP_FRAGMENT_INTERLEAVE, consider upgrading
515
-#endif /* SCTP_FRAGMENT_INTERLEAVE */
516
-	
517
-	/* turn off partial delivery: on linux setting SCTP_PARTIAL_DELIVERY_POINT
518
-	 * to 0 or a very large number seems to be enough, however the portable
519
-	 * way to do it is to set it to the socket receive buffer size
520
-	 * (this is the maximum value allowed in the sctp api draft) */
521
-#ifdef SCTP_PARTIAL_DELIVERY_POINT
522
-	optlen=sizeof(optval);
523
-	if (getsockopt(s, SOL_SOCKET, SO_RCVBUF,
524
-					(void*)&optval, &optlen) ==-1){
525
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: getsockopt: "
526
-						"SO_RCVBUF: %s\n", strerror(errno));
527
-		/* try to continue */
528
-		optval=0;
529
-	}
530
-#ifdef __OS_linux
531
-	optval/=2; /* in linux getsockopt() returns twice the set value */
532
-#endif
533
-	pd_point=optval;
534
-	saved_errno=0;
535
-	while(pd_point &&
536
-			setsockopt(s, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
537
-					(void*)&pd_point, sizeof(pd_point)) ==-1){
538
-		if (!saved_errno)
539
-			saved_errno=errno;
540
-		pd_point--;
541
-	}
542
-	
543
-	if (pd_point!=optval){
544
-		if (pd_point==0){
545
-			/* all attempts failed */
546
-			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
547
-						"SCTP_PARTIAL_DELIVERY_POINT (%d): %s\n",
548
-						optval, strerror(errno));
549
-			sctp_err++;
550
-			/* try to continue */
551
-		}else{
552
-			/* success but to a lower value (might not be disabled) */
553
-			LOG(L_WARN, "setsockopt SCTP_PARTIAL_DELIVERY_POINT set to %d, but"
554
-				" the socket rcvbuf is %d (higher values fail with"
555
-				" \"%s\" [%d])\n",
556
-				pd_point, optval, strerror(saved_errno), saved_errno);
557
-		}
558
-	}
559
-#else
560
-#warning no sctp lib support for SCTP_PARTIAL_DELIVERY_POINT, consider upgrading
561
-#endif /* SCTP_PARTIAL_DELIVERY_POINT */
562
-	
563
-	/* nagle / no delay */
564
-#ifdef SCTP_NODELAY
565
-	optval=1;
566
-	if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY,
567
-					(void*)&optval, sizeof(optval)) ==-1){
568
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
569
-						"SCTP_NODELAY: %s\n", strerror(errno));
570
-		sctp_err++;
571
-		/* non critical, try to continue */
572
-	}
573
-#else
574
-#warning no sctp lib support for SCTP_NODELAY, consider upgrading
575
-#endif /* SCTP_NODELAY */
576
-	
577
-	/* enable message fragmentation (SCTP_DISABLE_FRAGMENTS)  (on send) */
578
-#ifdef SCTP_DISABLE_FRAGMENTS
579
-	optval=0;
580
-	if (setsockopt(s, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS,
581
-					(void*)&optval, sizeof(optval)) ==-1){
582
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
583
-						"SCTP_DISABLE_FRAGMENTS: %s\n", strerror(errno));
584
-		sctp_err++;
585
-		/* non critical, try to continue */
586
-	}
587
-#else
588
-#warning no sctp lib support for SCTP_DISABLE_FRAGMENTS, consider upgrading
589
-#endif /* SCTP_DISABLE_FRAGMENTS */
590
-	
591
-	/* set autoclose */
592
-#ifdef SCTP_AUTOCLOSE
593
-	optval=cfg_get(sctp, sctp_cfg, autoclose);
594
-	if (setsockopt(s, IPPROTO_SCTP, SCTP_AUTOCLOSE,
595
-					(void*)&optval, sizeof(optval)) ==-1){
596
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
597
-						"SCTP_AUTOCLOSE: %s (critical)\n", strerror(errno));
598
-		/* critical: w/o autoclose we could have sctp connection living
599
-		   forever (if the remote side doesn't close them) */
600
-		sctp_err++;
601
-		goto error;
602
-	}
603
-#else
604
-#error SCTP_AUTOCLOSE not supported, please upgrade your sctp library
605
-#endif /* SCTP_AUTOCLOSE */
606
-	/* set rtoinfo options: srto_initial, srto_min, srto_max */
607
-#ifdef SCTP_RTOINFO
608
-	memset(&rto, 0, sizeof(rto));
609
-	rto.srto_initial=cfg_get(sctp, sctp_cfg, srto_initial);
610
-	rto.srto_min=cfg_get(sctp, sctp_cfg, srto_min);
611
-	rto.srto_max=cfg_get(sctp, sctp_cfg, srto_max);
612
-	if (rto.srto_initial || rto.srto_min || rto.srto_max){
613
-		/* if at least one is non-null => we have to set it */
614
-		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
615
-							sizeof(rto), "setsockopt: SCTP_RTOINFO")!=0){
616
-			sctp_err++;
617
-			/* non critical, try to continue */
618
-		}
619
-	}
620
-#else
621
-#warning no sctp lib support for SCTP_RTOINFO, consider upgrading
622
-#endif /* SCTP_RTOINFO */
623
-	/* set associnfo options: assocmaxrxt */
624
-#ifdef SCTP_ASSOCINFO
625
-	memset(&ap, 0, sizeof(ap));
626
-	ap.sasoc_asocmaxrxt=cfg_get(sctp, sctp_cfg, asocmaxrxt);
627
-	if (ap.sasoc_asocmaxrxt){
628
-		/* if at least one is non-null => we have to set it */
629
-		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_ASSOCINFO, (void*)&ap,
630
-							sizeof(ap), "setsockopt: SCTP_ASSOCINFO")!=0){
631
-			sctp_err++;
632
-			/* non critical, try to continue */
633
-		}
634
-	}
635
-#else
636
-#warning no sctp lib support for SCTP_ASSOCINFO, consider upgrading
637
-#endif /* SCTP_ASOCINFO */
638
-	/* set initmsg options: init_max_attempts & init_max_init_timeo */
639
-#ifdef SCTP_INITMSG
640
-	memset(&im, 0, sizeof(im));
641
-	im.sinit_max_attempts=cfg_get(sctp, sctp_cfg, init_max_attempts);
642
-	im.sinit_max_init_timeo=cfg_get(sctp, sctp_cfg, init_max_timeo);
643
-	if (im.sinit_max_attempts || im.sinit_max_init_timeo){
644
-		/* if at least one is non-null => we have to set it */
645
-		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, (void*)&im,
646
-							sizeof(im), "setsockopt: SCTP_INITMSG")!=0){
647
-			sctp_err++;
648
-			/* non critical, try to continue */
649
-		}
650
-	}
651
-#else
652
-#warning no sctp lib support for SCTP_INITMSG, consider upgrading
653
-#endif /* SCTP_INITMSG */
654
-	/* set sctp peer addr options: hbinterval & pathmaxrxt */
655
-#ifdef SCTP_PEER_ADDR_PARAMS
656
-	memset(&pp, 0, sizeof(pp));
657
-	pp.spp_address.ss_family=af;
658
-	pp.spp_hbinterval=cfg_get(sctp, sctp_cfg, hbinterval);
659
-	pp.spp_pathmaxrxt=cfg_get(sctp, sctp_cfg, pathmaxrxt);
660
-	if (pp.spp_hbinterval || pp.spp_pathmaxrxt){
661
-		if (pp.spp_hbinterval > 0)
662
-			pp.spp_flags=SPP_HB_ENABLE;
663
-		else if (pp.spp_hbinterval==-1){
664
-			pp.spp_flags=SPP_HB_DISABLE;
665
-			pp.spp_hbinterval=0;
666
-		}
667
-#ifdef __OS_linux
668
-		if (pp.spp_pathmaxrxt){
669
-			/* hack to work on linux, pathmaxrxt is set only if
670
-			   SPP_PMTUD_ENABLE */
671
-			pp.spp_flags|=SPP_PMTUD_ENABLE;
672
-		}
673
-#endif /*__OS_linux */
674
-		/* if at least one is non-null => we have to set it */
675
-		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, (void*)&pp,
676
-						sizeof(pp), "setsockopt: SCTP_PEER_ADDR_PARAMS")!=0){
677
-			sctp_err++;
678
-			/* non critical, try to continue */
679
-		}
680
-	}
681
-#else
682
-#warning no sctp lib support for SCTP_PEER_ADDR_PARAMS, consider upgrading
683
-#endif /* SCTP_PEER_ADDR_PARAMS */
684
-	/* set delayed ack options: sack_delay & sack_freq */
685
-#if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
686
-#ifdef SCTP_DELAYED_SACK
687
-	memset(&sack_info, 0, sizeof(sack_info));
688
-	sack_info.sack_delay=cfg_get(sctp, sctp_cfg, sack_delay);
689
-	sack_info.sack_freq=cfg_get(sctp, sctp_cfg, sack_freq);
690
-	if ((sack_info.sack_delay || sack_info.sack_freq) &&
691
-		(sctp_setsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_SACK,
692
-							(void*)&sack_info, sizeof(sack_info), 0)!=0)) {
693
-		/* if setting SCTP_DELAYED_SACK failed, try the old obsolete
694
-		   SCTP_DELAYED_ACK_TIME */
695
-#endif /* SCTP_DELAYED_SACK */
696
-#ifdef SCTP_DELAYED_ACK_TIME
697
-		memset(&sack_val, 0, sizeof(sack_val));
698
-		sack_val.assoc_value=cfg_get(sctp, sctp_cfg, sack_delay);
699
-		if (sack_val.assoc_value){
700
-			if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME,
701
-									(void*)&sack_val, sizeof(sack_val),
702
-									"setsockopt: SCTP_DELAYED_ACK_TIME")!=0){
703
-				sctp_err++;
704
-				/* non critical, try to continue */
705
-			}
706
-		}
707
-#else /* SCTP_DELAYED_ACK_TIME */
708
-		/* no SCTP_DELAYED_ACK_TIME support and SCTP_DELAYED_SACK failed
709
-		   => error */
710
-		if (sack_info.sack_delay){
711
-			sctp_err++;
712
-			ERR("cfg: setting SCTP_DELAYED_SACK: %s [%d]\n",
713
-						strerror(errno), errno);
714
-		}
715
-#endif /* SCTP_DELAYED_ACK_TIME */
716
-		if (cfg_get(sctp, sctp_cfg, sack_freq)){
717
-#ifdef SCTP_DELAYED_SACK
718
-			sctp_err++;
719
-			WARN("could not set sctp sack_freq, please upgrade your kernel\n");
720
-#else /* SCTP_DELAYED_SACK */
721
-			WARN("could not set sctp sack_freq, please upgrade your sctp"
722
-					" library\n");
723
-#endif /* SCTP_DELAYED_SACK */
724
-			((struct cfg_group_sctp*)sctp_cfg)->sack_freq=0;
725
-		}
726
-#ifdef SCTP_DELAYED_SACK
727
-	}
728
-#endif /* SCTP_DELAYED_SACK */
729
-	
730
-#else /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
731
-#warning no sctp lib support for SCTP_DELAYED_SACK, consider upgrading
732
-#endif /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
733
-	/* set max burst option */
734
-#ifdef SCTP_MAX_BURST
735
-	memset(&av, 0, sizeof(av));
736
-	av.assoc_value=cfg_get(sctp, sctp_cfg, max_burst);
737
-	if (av.assoc_value){
738
-		if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_MAX_BURST, (void*)&av,
739
-							sizeof(av), "setsockopt: SCTP_MAX_BURST")!=0){
740
-			sctp_err++;
741
-			/* non critical, try to continue */
742
-		}
743
-	}
744
-#else
745
-#warning no sctp lib support for SCTP_MAX_BURST, consider upgrading
746
-#endif /* SCTP_MAX_BURST */
747
-	
748
-	memset(&es, 0, sizeof(es));
749
-	/* SCTP_EVENTS for SCTP_SNDRCV (sctp_data_io_event) -> per message
750
-	 *  information in sctp_sndrcvinfo */
751
-	ev_s->sctp_data_io_event=1;
752
-	/* enable association event notifications */
753
-	ev_s->sctp_association_event=1; /* SCTP_ASSOC_CHANGE */
754
-	ev_s->sctp_address_event=1;  /* enable address events notifications */
755
-	ev_s->sctp_send_failure_event=1; /* SCTP_SEND_FAILED */
756
-	ev_s->sctp_peer_error_event=1;   /* SCTP_REMOTE_ERROR */
757
-	ev_s->sctp_shutdown_event=1;     /* SCTP_SHUTDOWN_EVENT */
758
-	ev_s->sctp_partial_delivery_event=1; /* SCTP_PARTIAL_DELIVERY_EVENT */
759
-	/* ev_s->sctp_adaptation_layer_event=1; - not supported by lksctp<=1.0.6*/
760
-	/* ev_s->sctp_authentication_event=1; -- not supported on linux 2.6.25 */
761
-	
762
-	/* enable the SCTP_EVENTS */
763
-#ifdef SCTP_EVENTS
764
-	if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, ev_s, sizeof(*ev_s))==-1){
765
-		/* on linux the checks for the struct sctp_event_subscribe size
766
-		   are too strict, making certain lksctp/kernel combination
767
-		   unworkable => since we don't use the extra information
768
-		   (sctp_authentication_event) added in newer version, we can
769
-		   try with different sizes) */
770
-#ifdef __OS_linux
771
-		/* 1. lksctp 1.0.9 with kernel < 2.6.26 -> kernel expects 
772
-		      the structure without the authentication event member */
773
-		if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, ev_s, sizeof(*ev_s)-1)==0)
774
-			goto ev_success;
775
-		/* 2. lksctp < 1.0.9? with kernel >= 2.6.26: the sctp.h structure
776
-		   does not have the authentication member, but the newer kernels 
777
-		   check only for optlen > sizeof(...) => we should never reach
778
-		   this point. */
779
-		/* 3. just to be foolproof if we reached this point, try
780
-		    with a bigger size before giving up  (out of desperation) */
781
-		if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, ev_s, sizeof(es))==0)
782
-			goto ev_success;
783
-
784
-#endif
785
-		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
786
-				"SCTP_EVENTS: %s\n", strerror(errno));
787
-		sctp_err++;
788
-		goto error; /* critical */
789
-	}
790
-#ifdef __OS_linux
791
-ev_success:
792
-#endif
793
-#else
794
-#error no sctp lib support for SCTP_EVENTS, consider upgrading
795
-#endif /* SCTP_EVENTS */
796
-	
797
-	if (sctp_err){
798
-		LOG(L_ERR, "ERROR: sctp: setting some sctp sockopts failed, "
799
-					"consider upgrading your kernel\n");
800
-	}
801
-	return 0;
802
-error:
803
-	return -1;
804
-}
805
-
806
-
807
-
808
-/* bind all addresses from sock (sockaddr_unions)
809
-   returns 0 on success, .1 on error */
810
-static int sctp_bind_sock(struct socket_info* sock_info)
811
-{
812
-	struct addr_info* ai;
813
-	union sockaddr_union* addr;
814
-	
815
-	addr=&sock_info->su;
816
-	/* bind the addresses*/
817
-	if (bind(sock_info->socket,  &addr->s, sockaddru_len(*addr))==-1){
818
-		LOG(L_ERR, "ERROR: sctp_bind_sock: bind(%x, %p, %d) on %s: %s\n",
819
-				sock_info->socket, &addr->s, 
820
-				(unsigned)sockaddru_len(*addr),
821
-				sock_info->address_str.s,
822
-				strerror(errno));
823
-		if (addr->s.sa_family==AF_INET6)
824
-			LOG(L_ERR, "ERROR: sctp_bind_sock: might be caused by using a "
825
-							"link local address, try site local or global\n");
826
-		goto error;
827
-	}
828
-	for (ai=sock_info->addr_info_lst; ai; ai=ai->next)
829
-		if (sctp_bindx(sock_info->socket, &ai->su.s, 1, SCTP_BINDX_ADD_ADDR)
830
-					==-1){
831
-			LOG(L_ERR, "ERROR: sctp_bind_sock: sctp_bindx(%x, %.*s:%d, 1, ...)"
832
-						" on %s:%d : [%d] %s (trying to continue)\n",
833
-						sock_info->socket,
834
-						ai->address_str.len, ai->address_str.s, 
835
-						sock_info->port_no,
836
-						sock_info->address_str.s, sock_info->port_no,
837
-						errno, strerror(errno));
838
-			if (ai->su.s.sa_family==AF_INET6)
839
-				LOG(L_ERR, "ERROR: sctp_bind_sock: might be caused by using a "
840
-							"link local address, try site local or global\n");
841
-			/* try to continue, a secondary address bind failure is not 
842
-			 * critical */
843
-		}
844
-	return 0;
845
-error:
846
-	return -1;
847
-}
848
-
849
-
850
-
851
-/* init, bind & start listening on the corresp. sctp socket
852
-   returns 0 on success, -1 on error */
853
-int sctp_init_sock(struct socket_info* sock_info)
854
-{
855
-	union sockaddr_union* addr;
856
-	
857
-	sock_info->proto=PROTO_SCTP;
858
-	addr=&sock_info->su;
859
-	if (sctp_init_su(sock_info)!=0)
860
-		goto error;
861
-	sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_SEQPACKET, 
862
-								IPPROTO_SCTP);
863
-	if (sock_info->socket==-1){
864
-		LOG(L_ERR, "ERROR: sctp_init_sock: socket: %s\n", strerror(errno));
865
-		goto error;
866
-	}
867
-	INFO("sctp: socket %d initialized (%p)\n", sock_info->socket, sock_info);
868
-	/* make socket non-blocking */
869
-#if 0
870
-	/* recvmsg must block so use blocking sockets
871
-	 * and send with MSG_DONTWAIT */
872
-	optval=fcntl(sock_info->socket, F_GETFL);
873
-	if (optval==-1){
874
-		LOG(L_ERR, "ERROR: init_sctp: fnctl failed: (%d) %s\n",
875
-				errno, strerror(errno));
876
-		goto error;
877
-	}
878
-	if (fcntl(sock_info->socket, F_SETFL, optval|O_NONBLOCK)==-1){
879
-		LOG(L_ERR, "ERROR: init_sctp: fcntl: set non-blocking failed:"
880
-				" (%d) %s\n", errno, strerror(errno));
881
-		goto error;
882
-	}
883
-#endif
884
-
885
-	/* set sock opts */
886
-	if (sctp_init_sock_opt_common(sock_info->socket, sock_info->address.af)!=0)
887
-		goto error;
888
-	/* SCTP_EVENTS for send dried out -> present in the draft not yet
889
-	 * present in linux (might help to detect when we could send again to
890
-	 * some peer, kind of poor's man poll on write, based on received
891
-	 * SCTP_SENDER_DRY_EVENTs */
892
-	
893
-	if (sctp_bind_sock(sock_info)<0)
894
-		goto error;
895
-	if (listen(sock_info->socket, 1)<0){
896
-		LOG(L_ERR, "ERROR: sctp_init_sock: listen(%x, 1) on %s: %s\n",
897
-					sock_info->socket, sock_info->address_str.s,
898
-					strerror(errno));
899
-		goto error;
900
-	}
901