sctp: workaround SCTP_DELAYED_SACK lksctp typo
[sip-router] / sctp_server.c
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 #ifdef USE_SCTP
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/sctp.h>
39 #include <errno.h>
40 #include <arpa/inet.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43
44
45 #include "sctp_sockopts.h"
46 #include "sctp_server.h"
47 #include "sctp_options.h"
48 #include "globals.h"
49 #include "config.h"
50 #include "dprint.h"
51 #include "receive.h"
52 #include "mem/mem.h"
53 #include "ip_addr.h"
54 #include "cfg/cfg_struct.h"
55 #ifdef USE_DST_BLACKLIST
56 #include "dst_blacklist.h"
57 #endif /* USE_DST_BLACKLIST */
58 #include "timer_ticks.h"
59 #include "clist.h"
60 #include "error.h"
61 #include "timer.h"
62 #include "sctp_stats.h"
63 #include "sctp_ev.h"
64
65
66
67 static atomic_t* sctp_conn_no;
68
69
70 #define ABORT_REASON_MAX_ASSOCS \
71         "Maximum configured number of open associations exceeded"
72
73 /* check if the underlying OS supports sctp
74    returns 0 if yes, -1 on error */
75 int sctp_check_support()
76 {
77         int s;
78         char buf[256];
79         
80         s = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
81         if (s!=-1){
82                 close(s);
83                 if (sctp_check_compiled_sockopts(buf, sizeof(buf))!=0){
84                         LOG(L_WARN, "WARNING: sctp: your ser version was compiled"
85                                                 " without support for the following sctp options: %s"
86                                                 ", which might cause unforseen problems \n", buf);
87                         LOG(L_WARN, "WARNING: sctp: please consider recompiling ser with"
88                                                 " an upgraded sctp library version\n");
89                 }
90                 return 0;
91         }
92         return -1;
93 }
94
95
96
97 /* append a token to a buffer (uses space between tokens) */
98 inline static void append_tok2buf(char* buf, int blen, char* tok)
99 {
100         char* p;
101         char* end;
102         int len;
103         
104         if (buf && blen){
105                 end=buf+blen;
106                 p=memchr(buf, 0, blen);
107                 if (p==0) goto error;
108                 if (p!=buf && p<(end-1)){
109                         *p=' ';
110                         p++;
111                 }
112                 len=MIN_int(strlen(tok), end-1-p);
113                 memcpy(p, tok, len);
114                 p[len]=0;
115         }
116 error:
117         return;
118 }
119
120
121
122 /* check if support fot all the needed sockopts  was compiled;
123    an ascii list of the unsuported options is returned in buf
124    returns 0 on success and  -number of unsuported options on failure
125    (<0 on failure)
126 */
127 int sctp_check_compiled_sockopts(char* buf, int size)
128 {
129         int err;
130
131         err=0;
132         if (buf && (size>0)) *buf=0; /* "" */
133 #ifndef SCTP_FRAGMENT_INTERLEAVE
134         err++;
135         append_tok2buf(buf, size, "SCTP_FRAGMENT_INTERLEAVE");
136 #endif
137 #ifndef SCTP_PARTIAL_DELIVERY_POINT
138         err++;
139         append_tok2buf(buf, size, "SCTP_PARTIAL_DELIVERY_POINT");
140 #endif
141 #ifndef SCTP_NODELAY
142         err++;
143         append_tok2buf(buf, size, "SCTP_NODELAY");
144 #endif
145 #ifndef SCTP_DISABLE_FRAGMENTS
146         err++;
147         append_tok2buf(buf, size, "SCTP_DISABLE_FRAGMENTS");
148 #endif
149 #ifndef SCTP_AUTOCLOSE
150         err++;
151         append_tok2buf(buf, size, "SCTP_AUTOCLOSE");
152 #endif
153 #ifndef SCTP_EVENTS
154         err++;
155         append_tok2buf(buf, size, "SCTP_EVENTS");
156 #endif
157         
158         return -err;
159 }
160
161
162
163 /* init all the sockaddr_union members of the socket_info struct
164    returns 0 on success and -1 on error */
165 inline static int sctp_init_su(struct socket_info* sock_info)
166 {
167         union sockaddr_union* addr;
168         struct addr_info* ai;
169         
170         addr=&sock_info->su;
171         if (init_su(addr, &sock_info->address, sock_info->port_no)<0){
172                 LOG(L_ERR, "ERROR: sctp_init_su: could not init sockaddr_union for"
173                                         "primary sctp address %.*s:%d\n",
174                                         sock_info->address_str.len, sock_info->address_str.s,
175                                         sock_info->port_no );
176                 goto error;
177         }
178         for (ai=sock_info->addr_info_lst; ai; ai=ai->next)
179                 if (init_su(&ai->su, &ai->address, sock_info->port_no)<0){
180                         LOG(L_ERR, "ERROR: sctp_init_su: could not init"
181                                         "backup sctp sockaddr_union for %.*s:%d\n",
182                                         ai->address_str.len, ai->address_str.s,
183                                         sock_info->port_no );
184                         goto error;
185                 }
186         return 0;
187 error:
188         return -1;
189 }
190
191
192
193 /** set a socket option (wrapper over setsockopt).
194   * @param err_prefix - if 0 no error message is printed on failure, if !=0
195   *                     it will be prepended to the error message.
196   * @return 0 on success, -1 on error */
197 int sctp_setsockopt(int s, int level, int optname, 
198                                         void* optval, socklen_t optlen, char* err_prefix)
199 {
200         if (setsockopt(s, level, optname, optval, optlen) ==-1){
201                 if (err_prefix)
202                         ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
203                 return -1;
204         }
205         return 0;
206 }
207
208
209
210 /** get a socket option (wrapper over getsockopt).
211   * @param err_prefix - if 0 no error message is printed on failure, if !=0
212   *                     it will be prepended to the error message.
213   * @return 0 on success, -1 on error */
214 int sctp_getsockopt(int s, int level, int optname, 
215                                         void* optval, socklen_t* optlen, char* err_prefix)
216 {
217         if (getsockopt(s, level, optname, optval, optlen) ==-1){
218                 if (err_prefix)
219                         ERR("%s: %s [%d]\n", err_prefix, strerror(errno), errno);
220                 return -1;
221         }
222         return 0;
223 }
224
225
226
227 /** get the os defaults for cfg options with os correspondents.
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 s;
234         int ret;
235         
236         s = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
237         if (s==-1)
238                 return -1;
239         ret=sctp_get_cfg_from_sock(s, cfg);
240         close(s);
241         return ret;
242 }
243
244
245
246 /** get the os cfg options from a specific socket.
247  *  @param s - intialized sctp socket
248  *  @param cfg - filled with the os defaults
249  *  @return -1 on error, 0 on success
250  */
251 int sctp_get_cfg_from_sock(int s, struct cfg_group_sctp* cfg)
252 {
253         int optval;
254         socklen_t optlen;
255 #ifdef SCTP_RTOINFO
256         struct sctp_rtoinfo rto;
257 #endif /* SCTP_RTOINFO */
258 #ifdef SCTP_ASSOCINFO
259         struct sctp_assocparams ap;
260 #endif /* SCTP_ASSOCINFO */
261 #ifdef SCTP_INITMSG
262         struct sctp_initmsg im;
263 #endif /* SCTP_INITMSG */
264 #ifdef SCTP_PEER_ADDR_PARAMS
265         struct sctp_paddrparams pp;
266 #endif /* SCTP_PEER_ADDR_PARAMS */
267 #ifdef  SCTP_DELAYED_SACK
268         struct sctp_sack_info sack_info;
269 #endif  /* SCTP_DELAYED_SACK */
270 #ifdef  SCTP_DELAYED_ACK_TIME
271         struct sctp_assoc_value sack_val; /* old version */
272 #endif /* SCTP_DELAYED_ACK_TIME */
273 #ifdef SCTP_MAX_BURST
274         struct sctp_assoc_value av;
275 #endif /* SCTP_MAX_BURST */
276         
277         /* SO_RCVBUF */
278         optlen=sizeof(int);
279         if (sctp_getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&optval,
280                                                         &optlen, "SO_RCVBUF")==0){
281                 /* success => hack to set the "default" values*/
282                 #ifdef __OS_linux
283                         optval/=2; /* in linux getsockopt() returns 2*set_value */
284                 #endif
285                 cfg->so_rcvbuf=optval;
286         }
287         /* SO_SNDBUF */
288         optlen=sizeof(int);
289         if (sctp_getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&optval,
290                                                         &optlen, "SO_SNDBUF")==0){
291                 /* success => hack to set the "default" values*/
292                 #ifdef __OS_linux
293                         optval/=2; /* in linux getsockopt() returns 2*set_value */
294                 #endif
295                 cfg->so_sndbuf=optval;
296         }
297         /* SCTP_AUTOCLOSE */
298 #ifdef SCTP_AUTOCLOSE
299         optlen=sizeof(int);
300         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_AUTOCLOSE, (void*)&optval,
301                                                         &optlen, "SCTP_AUTOCLOSE")==0){
302                 cfg->autoclose=optval;
303         }
304 #endif /* SCTP_AUTOCLOSE */
305         /* SCTP_RTOINFO -> srto_initial, srto_min, srto_max */
306 #ifdef SCTP_RTOINFO
307         optlen=sizeof(rto);
308         rto.srto_assoc_id=0;
309         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
310                                                         &optlen, "SCTP_RTOINFO")==0){
311                 /* success => hack to set the "default" values*/
312                 cfg->srto_initial=rto.srto_initial;
313                 cfg->srto_min=rto.srto_min;
314                 cfg->srto_max=rto.srto_max;
315         }
316 #endif /* SCTP_RTOINFO */
317 #ifdef SCTP_ASSOCINFO
318         optlen=sizeof(ap);
319         ap.sasoc_assoc_id=0;
320         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_ASSOCINFO, (void*)&ap,
321                                                         &optlen, "SCTP_ASSOCINFO")==0){
322                 /* success => hack to set the "default" values*/
323                 cfg->asocmaxrxt=ap.sasoc_asocmaxrxt;
324         }
325 #endif /* SCTP_ASSOCINFO */
326 #ifdef SCTP_INITMSG
327         optlen=sizeof(im);
328         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, (void*)&im,
329                                                         &optlen, "SCTP_INITMSG")==0){
330                 /* success => hack to set the "default" values*/
331                 cfg->init_max_attempts=im.sinit_max_attempts;
332                 cfg->init_max_timeo=im.sinit_max_init_timeo;
333         }
334 #endif /* SCTP_INITMSG */
335 #ifdef SCTP_PEER_ADDR_PARAMS
336         optlen=sizeof(pp);
337         memset(&pp, 0, sizeof(pp)); /* get defaults */
338         /* set the AF, needed on older linux kernels even for INADDR_ANY */
339         pp.spp_address.ss_family=AF_INET;
340         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, (void*)&pp,
341                                                         &optlen, "SCTP_PEER_ADDR_PARAMS")==0){
342                 /* success => hack to set the "default" values*/
343                 cfg->hbinterval=pp.spp_hbinterval;
344                 cfg->pathmaxrxt=pp.spp_pathmaxrxt;
345         }
346 #endif /* SCTP_PEER_ADDR_PARAMS */
347 #if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
348 #ifdef SCTP_DELAYED_SACK
349         optlen=sizeof(sack_info);
350         memset(&sack_info, 0, sizeof(sack_info));
351         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_SACK, (void*)&sack_info,
352                                                         &optlen, 0)==0){
353                 /* success => hack to set the "default" values*/
354                 cfg->sack_delay=sack_info.sack_delay;
355                 cfg->sack_freq=sack_info.sack_freq;
356         }else
357 #endif /* SCTP_DELAYED_SACK */
358         {
359 #ifdef  SCTP_DELAYED_ACK_TIME
360                 optlen=sizeof(sack_val);
361                 memset(&sack_val, 0, sizeof(sack_val));
362                 /* if no SCTP_DELAYED_SACK supported by the sctp lib, or setting it
363                    failed (not supported by the kernel) try using the obsolete
364                    SCTP_DELAYED_ACK_TIME method */
365                 if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME,
366                                                                 (void*)&sack_val, &optlen, 
367                                                                 "SCTP_DELAYED_ACK_TIME")==0){
368                         /* success => hack to set the "default" values*/
369                         cfg->sack_delay=sack_val.assoc_value;
370                         cfg->sack_freq=0; /* unknown */
371                 }
372 #else   /* SCTP_DELAYED_ACK_TIME */
373                 /* no SCTP_DELAYED_ACK_TIME support and SCTP_DELAYED_SACK failed
374                    => error */
375                 ERR("cfg: SCTP_DELAYED_SACK: %s [%d]\n", strerror(errno), errno);
376 #endif /* SCTP_DELAYED_ACK_TIME */
377         }
378 #endif /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
379 #ifdef SCTP_MAX_BURST
380         optlen=sizeof(av);
381         av.assoc_id=0;
382         if (sctp_getsockopt(s, IPPROTO_SCTP, SCTP_MAX_BURST, (void*)&av,
383                                                         &optlen, "SCTP_MAX_BURST")==0){
384                 /* success => hack to set the "default" values*/
385                 cfg->max_burst=av.assoc_value;
386         }
387 #endif /* SCTP_MAX_BURST */
388         
389         return 0;
390 }
391
392
393
394 /* set common (for one to many and one to one) sctp socket options
395    tries to ignore non-critical errors (it will only log them), for
396    improved portability (for example older linux kernel version support
397    only a limited number of sctp socket options)
398    returns 0 on success, -1 on error
399    WARNING: please keep it sync'ed w/ sctp_check_compiled_sockopts() */
400 static int sctp_init_sock_opt_common(int s, int af)
401 {
402         int optval;
403         int pd_point;
404         int saved_errno;
405         socklen_t optlen;
406         int sctp_err;
407 #ifdef SCTP_RTOINFO
408         struct sctp_rtoinfo rto;
409 #endif /* SCTP_RTOINFO */
410 #ifdef SCTP_ASSOCINFO
411         struct sctp_assocparams ap;
412 #endif /* SCTP_ASSOCINFO */
413 #ifdef SCTP_INITMSG
414         struct sctp_initmsg im;
415 #endif /* SCTP_INITMSG */
416 #ifdef SCTP_PEER_ADDR_PARAMS
417         struct sctp_paddrparams pp;
418 #endif /* SCTP_PEER_ADDR_PARAMS */
419 #ifdef SCTP_DELAYED_SACK
420         struct sctp_sack_info sack_info;
421 #endif  /* SCTP_DELAYED_SACK */
422 #ifdef  SCTP_DELAYED_ACK_TIME
423         struct sctp_assoc_value sack_val;
424 #endif /* defined SCTP_DELAYED_ACK_TIME */
425 #ifdef SCTP_MAX_BURST
426         struct sctp_assoc_value av;
427 #endif /* SCTP_MAX_BURST */
428         
429 #ifdef __OS_linux
430         union {
431                 struct sctp_event_subscribe s;
432                 char padding[sizeof(struct sctp_event_subscribe)+sizeof(__u8)];
433         } es;
434 #else
435         struct sctp_event_subscribe es;
436 #endif
437         struct sctp_event_subscribe* ev_s;
438         
439         sctp_err=0;
440 #ifdef __OS_linux
441         ev_s=&es.s;
442 #else
443         ev_s=&es;
444 #endif
445         /* set tos */
446         optval = tos;
447         if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval,sizeof(optval)) ==-1){
448                 LOG(L_WARN, "WARNING: sctp_init_sock_opt_common: setsockopt tos: %s\n",
449                                 strerror(errno));
450                 /* continue since this is not critical */
451         }
452         
453         /* set receive buffer: SO_RCVBUF*/
454         if (cfg_get(sctp, sctp_cfg, so_rcvbuf)){
455                 optval=cfg_get(sctp, sctp_cfg, so_rcvbuf);
456                 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
457                                         (void*)&optval, sizeof(optval)) ==-1){
458                         LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
459                                                 " SO_RCVBUF (%d): %s\n", optval, strerror(errno));
460                         /* continue, non-critical */
461                 }
462         }
463         
464         /* set send buffer: SO_SNDBUF */
465         if (cfg_get(sctp, sctp_cfg, so_sndbuf)){
466                 optval=cfg_get(sctp, sctp_cfg, so_sndbuf);
467                 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
468                                         (void*)&optval, sizeof(optval)) ==-1){
469                         LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
470                                                 " SO_SNDBUF (%d): %s\n", optval, strerror(errno));
471                         /* continue, non-critical */
472                 }
473         }
474         
475         /* set reuseaddr */
476         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
477                                                 (void*)&optval, sizeof(optval))==-1){
478                         LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
479                                                 " SO_REUSEADDR (%d): %s\n", optval, strerror(errno));
480                         /* continue, non-critical */
481         }
482
483         
484         /* disable fragments interleave (SCTP_FRAGMENT_INTERLEAVE) --
485          * we don't want partial delivery, so fragment interleave must be off too
486          */
487 #ifdef SCTP_FRAGMENT_INTERLEAVE
488         optval=0;
489         if (setsockopt(s, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE ,
490                                         (void*)&optval, sizeof(optval)) ==-1){
491                 LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
492                                         "SCTP_FRAGMENT_INTERLEAVE: %s\n", strerror(errno));
493                 sctp_err++;
494                 /* try to continue */
495         }
496 #else
497 #warning no sctp lib support for SCTP_FRAGMENT_INTERLEAVE, consider upgrading
498 #endif /* SCTP_FRAGMENT_INTERLEAVE */
499         
500         /* turn off partial delivery: on linux setting SCTP_PARTIAL_DELIVERY_POINT
501          * to 0 or a very large number seems to be enough, however the portable
502          * way to do it is to set it to the socket receive buffer size
503          * (this is the maximum value allowed in the sctp api draft) */
504 #ifdef SCTP_PARTIAL_DELIVERY_POINT
505         optlen=sizeof(optval);
506         if (getsockopt(s, SOL_SOCKET, SO_RCVBUF,
507                                         (void*)&optval, &optlen) ==-1){
508                 LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: getsockopt: "
509                                                 "SO_RCVBUF: %s\n", strerror(errno));
510                 /* try to continue */
511                 optval=0;
512         }
513 #ifdef __OS_linux
514         optval/=2; /* in linux getsockopt() returns twice the set value */
515 #endif
516         pd_point=optval;
517         saved_errno=0;
518         while(pd_point &&
519                         setsockopt(s, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
520                                         (void*)&pd_point, sizeof(pd_point)) ==-1){
521                 if (!saved_errno)
522                         saved_errno=errno;
523                 pd_point--;
524         }
525         
526         if (pd_point!=optval){
527                 if (pd_point==0){
528                         /* all attempts failed */
529                         LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
530                                                 "SCTP_PARTIAL_DELIVERY_POINT (%d): %s\n",
531                                                 optval, strerror(errno));
532                         sctp_err++;
533                         /* try to continue */
534                 }else{
535                         /* success but to a lower value (might not be disabled) */
536                         LOG(L_WARN, "setsockopt SCTP_PARTIAL_DELIVERY_POINT set to %d, but"
537                                 " the socket rcvbuf is %d (higher values fail with"
538                                 " \"%s\" [%d])\n",
539                                 pd_point, optval, strerror(saved_errno), saved_errno);
540                 }
541         }
542 #else
543 #warning no sctp lib support for SCTP_PARTIAL_DELIVERY_POINT, consider upgrading
544 #endif /* SCTP_PARTIAL_DELIVERY_POINT */
545         
546         /* nagle / no delay */
547 #ifdef SCTP_NODELAY
548         optval=1;
549         if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY,
550                                         (void*)&optval, sizeof(optval)) ==-1){
551                 LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
552                                                 "SCTP_NODELAY: %s\n", strerror(errno));
553                 sctp_err++;
554                 /* non critical, try to continue */
555         }
556 #else
557 #warning no sctp lib support for SCTP_NODELAY, consider upgrading
558 #endif /* SCTP_NODELAY */
559         
560         /* enable message fragmentation (SCTP_DISABLE_FRAGMENTS)  (on send) */
561 #ifdef SCTP_DISABLE_FRAGMENTS
562         optval=0;
563         if (setsockopt(s, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS,
564                                         (void*)&optval, sizeof(optval)) ==-1){
565                 LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
566                                                 "SCTP_DISABLE_FRAGMENTS: %s\n", strerror(errno));
567                 sctp_err++;
568                 /* non critical, try to continue */
569         }
570 #else
571 #warning no sctp lib support for SCTP_DISABLE_FRAGMENTS, consider upgrading
572 #endif /* SCTP_DISABLE_FRAGMENTS */
573         
574         /* set autoclose */
575 #ifdef SCTP_AUTOCLOSE
576         optval=cfg_get(sctp, sctp_cfg, autoclose);
577         if (setsockopt(s, IPPROTO_SCTP, SCTP_AUTOCLOSE,
578                                         (void*)&optval, sizeof(optval)) ==-1){
579                 LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
580                                                 "SCTP_AUTOCLOSE: %s (critical)\n", strerror(errno));
581                 /* critical: w/o autoclose we could have sctp connection living
582                    forever (if the remote side doesn't close them) */
583                 sctp_err++;
584                 goto error;
585         }
586 #else
587 #error SCTP_AUTOCLOSE not supported, please upgrade your sctp library
588 #endif /* SCTP_AUTOCLOSE */
589         /* set rtoinfo options: srto_initial, srto_min, srto_max */
590 #ifdef SCTP_RTOINFO
591         memset(&rto, 0, sizeof(rto));
592         rto.srto_initial=cfg_get(sctp, sctp_cfg, srto_initial);
593         rto.srto_min=cfg_get(sctp, sctp_cfg, srto_min);
594         rto.srto_max=cfg_get(sctp, sctp_cfg, srto_max);
595         if (rto.srto_initial || rto.srto_min || rto.srto_max){
596                 /* if at least one is non-null => we have to set it */
597                 if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_RTOINFO, (void*)&rto,
598                                                         sizeof(rto), "setsockopt: SCTP_RTOINFO")!=0){
599                         sctp_err++;
600                         /* non critical, try to continue */
601                 }
602         }
603 #else
604 #warning no sctp lib support for SCTP_RTOINFO, consider upgrading
605 #endif /* SCTP_RTOINFO */
606         /* set associnfo options: assocmaxrxt */
607 #ifdef SCTP_ASSOCINFO
608         memset(&ap, 0, sizeof(ap));
609         ap.sasoc_asocmaxrxt=cfg_get(sctp, sctp_cfg, asocmaxrxt);
610         if (ap.sasoc_asocmaxrxt){
611                 /* if at least one is non-null => we have to set it */
612                 if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_ASSOCINFO, (void*)&ap,
613                                                         sizeof(ap), "setsockopt: SCTP_ASSOCINFO")!=0){
614                         sctp_err++;
615                         /* non critical, try to continue */
616                 }
617         }
618 #else
619 #warning no sctp lib support for SCTP_ASSOCINFO, consider upgrading
620 #endif /* SCTP_ASOCINFO */
621         /* set initmsg options: init_max_attempts & init_max_init_timeo */
622 #ifdef SCTP_INITMSG
623         memset(&im, 0, sizeof(im));
624         im.sinit_max_attempts=cfg_get(sctp, sctp_cfg, init_max_attempts);
625         im.sinit_max_init_timeo=cfg_get(sctp, sctp_cfg, init_max_timeo);
626         if (im.sinit_max_attempts || im.sinit_max_init_timeo){
627                 /* if at least one is non-null => we have to set it */
628                 if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, (void*)&im,
629                                                         sizeof(im), "setsockopt: SCTP_INITMSG")!=0){
630                         sctp_err++;
631                         /* non critical, try to continue */
632                 }
633         }
634 #else
635 #warning no sctp lib support for SCTP_INITMSG, consider upgrading
636 #endif /* SCTP_INITMSG */
637         /* set sctp peer addr options: hbinterval & pathmaxrxt */
638 #ifdef SCTP_PEER_ADDR_PARAMS
639         memset(&pp, 0, sizeof(pp));
640         pp.spp_address.ss_family=af;
641         pp.spp_hbinterval=cfg_get(sctp, sctp_cfg, hbinterval);
642         pp.spp_pathmaxrxt=cfg_get(sctp, sctp_cfg, pathmaxrxt);
643         if (pp.spp_hbinterval || pp.spp_pathmaxrxt){
644                 if (pp.spp_hbinterval > 0)
645                         pp.spp_flags=SPP_HB_ENABLE;
646                 else if (pp.spp_hbinterval==-1){
647                         pp.spp_flags=SPP_HB_DISABLE;
648                         pp.spp_hbinterval=0;
649                 }
650 #ifdef __OS_linux
651                 if (pp.spp_pathmaxrxt){
652                         /* hack to work on linux, pathmaxrxt is set only if
653                            SPP_PMTUD_ENABLE */
654                         pp.spp_flags|=SPP_PMTUD_ENABLE;
655                 }
656 #endif /*__OS_linux */
657                 /* if at least one is non-null => we have to set it */
658                 if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, (void*)&pp,
659                                                 sizeof(pp), "setsockopt: SCTP_PEER_ADDR_PARAMS")!=0){
660                         sctp_err++;
661                         /* non critical, try to continue */
662                 }
663         }
664 #else
665 #warning no sctp lib support for SCTP_PEER_ADDR_PARAMS, consider upgrading
666 #endif /* SCTP_PEER_ADDR_PARAMS */
667         /* set delayed ack options: sack_delay & sack_freq */
668 #if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
669 #ifdef SCTP_DELAYED_SACK
670         memset(&sack_info, 0, sizeof(sack_info));
671         sack_info.sack_delay=cfg_get(sctp, sctp_cfg, sack_delay);
672         sack_info.sack_freq=cfg_get(sctp, sctp_cfg, sack_freq);
673         if ((sack_info.sack_delay || sack_info.sack_freq) &&
674                 (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_SACK,
675                                                         (void*)&sack_info, sizeof(sack_info), 0)!=0)) {
676                 /* if setting SCTP_DELAYED_SACK failed, try the old obsolete
677                    SCTP_DELAYED_ACK_TIME */
678 #endif /* SCTP_DELAYED_SACK */
679 #ifdef SCTP_DELAYED_ACK_TIME
680                 memset(&sack_val, 0, sizeof(sack_val));
681                 sack_val.assoc_value=cfg_get(sctp, sctp_cfg, sack_delay);
682                 if (sack_val.assoc_value){
683                         if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME,
684                                                                         (void*)&sack_val, sizeof(sack_val),
685                                                                         "setsockopt: SCTP_DELAYED_ACK_TIME")!=0){
686                                 sctp_err++;
687                                 /* non critical, try to continue */
688                         }
689                 }
690 #else /* SCTP_DELAYED_ACK_TIME */
691                 /* no SCTP_DELAYED_ACK_TIME support and SCTP_DELAYED_SACK failed
692                    => error */
693                 if (sack_info.sack_delay){
694                         sctp_err++;
695                         ERR("cfg: setting SCTP_DELAYED_SACK: %s [%d]\n",
696                                                 strerror(errno), errno);
697                 }
698 #endif /* SCTP_DELAYED_ACK_TIME */
699                 if (cfg_get(sctp, sctp_cfg, sack_freq)){
700 #ifdef SCTP_DELAYED_SACK
701                         sctp_err++;
702                         WARN("could not set sctp sack_freq, please upgrade your kernel\n");
703 #else /* SCTP_DELAYED_SACK */
704                         WARN("could not set sctp sack_freq, please upgrade your sctp"
705                                         " library\n");
706 #endif /* SCTP_DELAYED_SACK */
707                         ((struct cfg_group_sctp*)sctp_cfg)->sack_freq=0;
708                 }
709 #ifdef SCTP_DELAYED_SACK
710         }
711 #endif /* SCTP_DELAYED_SACK */
712         
713 #else /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
714 #warning no sctp lib support for SCTP_DELAYED_SACK, consider upgrading
715 #endif /* SCTP_DELAYED_SACK  | SCTP_DELAYED_ACK_TIME*/
716         /* set max burst option */
717 #ifdef SCTP_MAX_BURST
718         memset(&av, 0, sizeof(av));
719         av.assoc_value=cfg_get(sctp, sctp_cfg, max_burst);
720         if (av.assoc_value){
721                 if (sctp_setsockopt(s, IPPROTO_SCTP, SCTP_MAX_BURST, (void*)&av,
722                                                         sizeof(av), "setsockopt: SCTP_MAX_BURST")!=0){
723                         sctp_err++;
724                         /* non critical, try to continue */
725                 }
726         }
727 #else
728 #warning no sctp lib support for SCTP_MAX_BURST, consider upgrading
729 #endif /* SCTP_MAX_BURST */
730         
731         memset(&es, 0, sizeof(es));
732         /* SCTP_EVENTS for SCTP_SNDRCV (sctp_data_io_event) -> per message
733          *  information in sctp_sndrcvinfo */
734         ev_s->sctp_data_io_event=1;
735         /* enable association event notifications */
736         ev_s->sctp_association_event=1; /* SCTP_ASSOC_CHANGE */
737         ev_s->sctp_address_event=1;  /* enable address events notifications */
738         ev_s->sctp_send_failure_event=1; /* SCTP_SEND_FAILED */
739         ev_s->sctp_peer_error_event=1;   /* SCTP_REMOTE_ERROR */
740         ev_s->sctp_shutdown_event=1;     /* SCTP_SHUTDOWN_EVENT */
741         ev_s->sctp_partial_delivery_event=1; /* SCTP_PARTIAL_DELIVERY_EVENT */
742         /* ev_s->sctp_adaptation_layer_event=1; - not supported by lksctp<=1.0.6*/
743         /* ev_s->sctp_authentication_event=1; -- not supported on linux 2.6.25 */
744         
745         /* enable the SCTP_EVENTS */
746 #ifdef SCTP_EVENTS
747         if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, ev_s, sizeof(*ev_s))==-1){
748                 /* on linux the checks for the struct sctp_event_subscribe size
749                    are too strict, making certain lksctp/kernel combination
750                    unworkable => since we don't use the extra information
751                    (sctp_authentication_event) added in newer version, we can
752                    try with different sizes) */
753 #ifdef __OS_linux
754                 /* 1. lksctp 1.0.9 with kernel < 2.6.26 -> kernel expects 
755                       the structure without the authentication event member */
756                 if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, ev_s, sizeof(*ev_s)-1)==0)
757                         goto ev_success;
758                 /* 2. lksctp < 1.0.9? with kernel >= 2.6.26: the sctp.h structure
759                    does not have the authentication member, but the newer kernels 
760                    check only for optlen > sizeof(...) => we should never reach
761                    this point. */
762                 /* 3. just to be foolproof if we reached this point, try
763                     with a bigger size before giving up  (out of desperation) */
764                 if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, ev_s, sizeof(es))==0)
765                         goto ev_success;
766
767 #endif
768                 LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
769                                 "SCTP_EVENTS: %s\n", strerror(errno));
770                 sctp_err++;
771                 goto error; /* critical */
772         }
773 #ifdef __OS_linux
774 ev_success:
775 #endif
776 #else
777 #error no sctp lib support for SCTP_EVENTS, consider upgrading
778 #endif /* SCTP_EVENTS */
779         
780         if (sctp_err){
781                 LOG(L_ERR, "ERROR: sctp: setting some sctp sockopts failed, "
782                                         "consider upgrading your kernel\n");
783         }
784         return 0;
785 error:
786         return -1;
787 }
788
789
790
791 /* bind all addresses from sock (sockaddr_unions)
792    returns 0 on success, .1 on error */
793 static int sctp_bind_sock(struct socket_info* sock_info)
794 {
795         struct addr_info* ai;
796         union sockaddr_union* addr;
797         
798         addr=&sock_info->su;
799         /* bind the addresses*/
800         if (bind(sock_info->socket,  &addr->s, sockaddru_len(*addr))==-1){
801                 LOG(L_ERR, "ERROR: sctp_bind_sock: bind(%x, %p, %d) on %s: %s\n",
802                                 sock_info->socket, &addr->s, 
803                                 (unsigned)sockaddru_len(*addr),
804                                 sock_info->address_str.s,
805                                 strerror(errno));
806         #ifdef USE_IPV6
807                 if (addr->s.sa_family==AF_INET6)
808                         LOG(L_ERR, "ERROR: sctp_bind_sock: might be caused by using a "
809                                                         "link local address, try site local or global\n");
810         #endif
811                 goto error;
812         }
813         for (ai=sock_info->addr_info_lst; ai; ai=ai->next)
814                 if (sctp_bindx(sock_info->socket, &ai->su.s, 1, SCTP_BINDX_ADD_ADDR)
815                                         ==-1){
816                         LOG(L_ERR, "ERROR: sctp_bind_sock: sctp_bindx(%x, %.*s:%d, 1, ...)"
817                                                 " on %s:%d : [%d] %s (trying to continue)\n",
818                                                 sock_info->socket,
819                                                 ai->address_str.len, ai->address_str.s, 
820                                                 sock_info->port_no,
821                                                 sock_info->address_str.s, sock_info->port_no,
822                                                 errno, strerror(errno));
823                 #ifdef USE_IPV6
824                         if (ai->su.s.sa_family==AF_INET6)
825                                 LOG(L_ERR, "ERROR: sctp_bind_sock: might be caused by using a "
826                                                         "link local address, try site local or global\n");
827                 #endif
828                         /* try to continue, a secondary address bind failure is not 
829                          * critical */
830                 }
831         return 0;
832 error:
833         return -1;
834 }
835
836
837
838 /* init, bind & start listening on the corresp. sctp socket
839    returns 0 on success, -1 on error */
840 int sctp_init_sock(struct socket_info* sock_info)
841 {
842         union sockaddr_union* addr;
843         
844         sock_info->proto=PROTO_SCTP;
845         addr=&sock_info->su;
846         if (sctp_init_su(sock_info)!=0)
847                 goto error;
848         sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_SEQPACKET, 
849                                                                 IPPROTO_SCTP);
850         if (sock_info->socket==-1){
851                 LOG(L_ERR, "ERROR: sctp_init_sock: socket: %s\n", strerror(errno));
852                 goto error;
853         }
854         INFO("sctp: socket %d initialized (%p)\n", sock_info->socket, sock_info);
855         /* make socket non-blocking */
856 #if 0
857         /* recvmsg must block so use blocking sockets
858          * and send with MSG_DONTWAIT */
859         optval=fcntl(sock_info->socket, F_GETFL);
860         if (optval==-1){
861                 LOG(L_ERR, "ERROR: init_sctp: fnctl failed: (%d) %s\n",
862                                 errno, strerror(errno));
863                 goto error;
864         }
865         if (fcntl(sock_info->socket, F_SETFL, optval|O_NONBLOCK)==-1){
866                 LOG(L_ERR, "ERROR: init_sctp: fcntl: set non-blocking failed:"
867                                 " (%d) %s\n", errno, strerror(errno));
868                 goto error;
869         }
870 #endif
871
872         /* set sock opts */
873         if (sctp_init_sock_opt_common(sock_info->socket, sock_info->address.af)!=0)
874                 goto error;
875         /* SCTP_EVENTS for send dried out -> present in the draft not yet
876          * present in linux (might help to detect when we could send again to
877          * some peer, kind of poor's man poll on write, based on received
878          * SCTP_SENDER_DRY_EVENTs */
879         
880         if (sctp_bind_sock(sock_info)<0)
881                 goto error;
882         if (listen(sock_info->socket, 1)<0){
883                 LOG(L_ERR, "ERROR: sctp_init_sock: listen(%x, 1) on %s: %s\n",
884                                         sock_info->socket, sock_info->address_str.s,
885                                         strerror(errno));
886                 goto error;
887         }
888         return 0;
889 error:
890         return -1;
891 }
892
893
894 #define USE_SCTP_OO
895
896 #ifdef USE_SCTP_OO
897
898 /* init, bind & start listening on the corresp. sctp socket, using
899    sctp one-to-one mode
900    returns 0 on success, -1 on error */
901 int sctp_init_sock_oo(struct socket_info* sock_info)
902 {
903         union sockaddr_union* addr;
904         int optval;
905         
906         sock_info->proto=PROTO_SCTP;
907         addr=&sock_info->su;
908         if (sctp_init_su(sock_info)!=0)
909                 goto error;
910         sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 
911                                                                 IPPROTO_SCTP);
912         if (sock_info->socket==-1){
913                 LOG(L_ERR, "ERROR: sctp_init_sock_oo: socket: %s\n", strerror(errno));
914                 goto error;
915         }
916         INFO("sctp:oo socket %d initialized (%p)\n", sock_info->socket, sock_info);
917         /* make socket non-blocking */
918         optval=fcntl(sock_info->socket, F_GETFL);
919         if (optval==-1){
920                 LOG(L_ERR, "ERROR: sctp_init_sock_oo: fnctl failed: (%d) %s\n",
921                                 errno, strerror(errno));
922                 goto error;
923         }
924         if (fcntl(sock_info->socket, F_SETFL, optval|O_NONBLOCK)==-1){
925                 LOG(L_ERR, "ERROR: sctp_init_sock_oo: fcntl: set non-blocking failed:"
926                                 " (%d) %s\n", errno, strerror(errno));
927                 goto error;
928         }
929         
930         /* set sock opts */
931         if (sctp_init_sock_opt_common(sock_info->socket, sock_info->address.af)!=0)
932                 goto error;
933         
934 #ifdef SCTP_REUSE_PORT
935         /* set reuse port */
936         optval=1;
937         if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_REUSE_PORT ,
938                                         (void*)&optval, sizeof(optval)) ==-1){
939                 LOG(L_ERR, "ERROR: sctp_init_sock_oo: setsockopt: "
940                                         "SCTP_REUSE_PORT: %s\n", strerror(errno));
941                 goto error;
942         }
943 #endif /* SCTP_REUSE_PORT */
944         
945         if (sctp_bind_sock(sock_info)<0)
946                 goto error;
947         if (listen(sock_info->socket, 1)<0){
948                 LOG(L_ERR, "ERROR: sctp_init_sock_oo: listen(%x, 1) on %s: %s\n",
949                                         sock_info->socket, sock_info->address_str.s,
950                                         strerror(errno));
951                 goto error;
952         }
953         return 0;
954 error:
955         return -1;
956 }
957
958 #endif /* USE_SCTP_OO */
959
960
961 #ifdef SCTP_CONN_REUSE
962
963 /* we  need SCTP_ADDR_HASH for being able to make inquires related to existing
964    sctp association to a particular address  (optional) */
965 /*#define SCTP_ADDR_HASH*/
966
967 #define SCTP_ID_HASH_SIZE 1024 /* must be 2^k */
968 #define SCTP_ASSOC_HASH_SIZE 1024 /* must be 2^k */
969 #define SCTP_ADDR_HASH_SIZE 1024 /* must be 2^k */
970
971 /* lock method */
972 #ifdef GEN_LOCK_T_UNLIMITED
973 #define SCTP_HASH_LOCK_PER_BUCKET
974 #elif defined GEN_LOCK_SET_T_UNLIMITED
975 #define SCTP_HASH_LOCK_SET
976 #else
977 #define SCTP_HASH_ONE_LOCK
978 #endif
979
980
981 #ifdef SCTP_HASH_LOCK_PER_BUCKET
982 /* lock included in the hash bucket */
983 #define LOCK_SCTP_ID_H(h)               lock_get(&sctp_con_id_hash[(h)].lock)
984 #define UNLOCK_SCTP_ID_H(h)             lock_release(&sctp_con_id_hash[(h)].lock)
985 #define LOCK_SCTP_ASSOC_H(h)    lock_get(&sctp_con_assoc_hash[(h)].lock)
986 #define UNLOCK_SCTP_ASSOC_H(h)  lock_release(&sctp_con_assoc_hash[(h)].lock)
987 #define LOCK_SCTP_ADDR_H(h)             lock_get(&sctp_con_addr_hash[(h)].lock)
988 #define UNLOCK_SCTP_ADDR_H(h)   lock_release(&sctp_con_addr_hash[(h)].lock)
989 #elif defined SCTP_HASH_LOCK_SET
990 static gen_lock_set_t* sctp_con_id_h_lock_set=0;
991 static gen_lock_set_t* sctp_con_assoc_h_lock_set=0;
992 static gen_lock_set_t* sctp_con_addr_h_lock_set=0;
993 #define LOCK_SCTP_ID_H(h)               lock_set_get(sctp_con_id_h_lock_set, (h))
994 #define UNLOCK_SCTP_ID_H(h)             lock_set_release(sctp_con_id_h_lock_set, (h))
995 #define LOCK_SCTP_ASSOC_H(h)    lock_set_get(sctp_con_assoc_h_lock_set, (h))
996 #define UNLOCK_SCTP_ASSOC_H(h)  \
997         lock_set_release(sctp_con_assoc_h_lock_set, (h))
998 #define LOCK_SCTP_ADDR_H(h)     lock_set_get(sctp_con_addr_h_lock_set, (h))
999 #define UNLOCK_SCTP_ADDR_H(h)   lock_set_release(sctp_con_addr_h_lock_set, (h))
1000 #else /* use only one lock */
1001 static gen_lock_t* sctp_con_id_h_lock=0;
1002 static gen_lock_t* sctp_con_assoc_h_lock=0;
1003 static gen_lock_t* sctp_con_addr_h_lock=0;
1004 #define LOCK_SCTP_ID_H(h)               lock_get(sctp_con_id_h_lock)
1005 #define UNLOCK_SCTP_ID_H(h)             lock_release(sctp_con_id_hlock)
1006 #define LOCK_SCTP_ASSOC_H(h)    lock_get(sctp_con_assoc_h_lock)
1007 #define UNLOCK_SCTP_ASSOC_H(h)  lock_release(sctp_con_assoc_h_lock)
1008 #define LOCK_SCTP_ADDR_H(h)     lock_get(sctp_con_addr_h_lock)
1009 #define UNLOCK_SCTP_ADDR_H(h)   lock_release(sctp_con_addr_h_lock)
1010 #endif /* SCTP_HASH_LOCK_PER_BUCKET */
1011
1012
1013 /* sctp connection flags */
1014 #define SCTP_CON_UP_SEEN   1
1015 #define SCTP_CON_RCV_SEEN  2
1016 #define SCTP_CON_DOWN_SEEN 4
1017
1018 struct sctp_connection{
1019         unsigned int id;       /**< ser unique global id */
1020         unsigned int assoc_id; /**< sctp assoc id (can be reused for new assocs)*/
1021         struct socket_info* si; /**< local socket used */
1022         unsigned flags; /**< internal flags UP_SEEN, RCV_SEEN, DOWN_SEEN */
1023         ticks_t start;
1024         ticks_t expire; 
1025         union sockaddr_union remote; /**< remote ip & port */
1026 };
1027
1028 struct sctp_lst_connector{
1029         /* id hash */
1030         struct sctp_con_elem* next_id;
1031         struct sctp_con_elem* prev_id;
1032         /* assoc hash */
1033         struct sctp_con_elem* next_assoc;
1034         struct sctp_con_elem* prev_assoc;
1035 #ifdef SCTP_ADDR_HASH
1036         /* addr hash */
1037         struct sctp_con_elem* next_addr;
1038         struct sctp_con_elem* prev_addr;
1039 #endif /* SCTP_ADDR_HASH */
1040 };
1041
1042 struct sctp_con_elem{
1043         struct sctp_lst_connector l; /* must be first */
1044         atomic_t refcnt;
1045         /* data */
1046         struct sctp_connection con;
1047 };
1048
1049 struct sctp_con_id_hash_head{
1050         struct sctp_lst_connector l; /* must be first */
1051 #ifdef SCTP_HASH_LOCK_PER_BUCKET
1052         gen_lock_t lock;
1053 #endif /* SCTP_HASH_LOCK_PER_BUCKET */
1054 };
1055
1056 struct sctp_con_assoc_hash_head{
1057         struct sctp_lst_connector l; /* must be first */
1058 #ifdef SCTP_HASH_LOCK_PER_BUCKET
1059         gen_lock_t lock;
1060 #endif /* SCTP_HASH_LOCK_PER_BUCKET */
1061 };
1062
1063 #ifdef SCTP_ADDR_HASH
1064 struct sctp_con_addr_hash_head{
1065         struct sctp_lst_connector l; /* must be first */
1066 #ifdef SCTP_HASH_LOCK_PER_BUCKET
1067         gen_lock_t lock;
1068 #endif /* SCTP_HASH_LOCK_PER_BUCKET */
1069 };
1070 #endif /* SCTP_ADDR_HASH */
1071
1072 static struct sctp_con_id_hash_head*     sctp_con_id_hash;
1073 static struct sctp_con_assoc_hash_head*  sctp_con_assoc_hash;
1074 #ifdef SCTP_ADDR_HASH
1075 static struct sctp_con_addr_hash_head*  sctp_con_addr_hash;
1076 #endif /* SCTP_ADDR_HASH */
1077
1078 static atomic_t* sctp_id;
1079 static atomic_t* sctp_conn_tracked;
1080
1081
1082 #define get_sctp_con_id_hash(id) ((id) % SCTP_ID_HASH_SIZE)
1083 #define get_sctp_con_assoc_hash(assoc_id)  ((assoc_id) % SCTP_ASSOC_HASH_SIZE)
1084 #ifdef SCTP_ADDR_HASH
1085 static inline unsigned get_sctp_con_addr_hash(union sockaddr_union* remote,
1086                                                                                         struct socket_info* si)
1087 {
1088         struct ip_addr ip;
1089         unsigned short port;
1090         unsigned h;
1091         
1092         su2ip_addr(&ip, remote);
1093         port=su_getport(remote);
1094         if (likely(ip.len==4))
1095                 h=ip.u.addr32[0]^port;
1096         else if (ip.len==16)
1097                 h=ip.u.addr32[0]^ip.u.addr32[1]^ip.u.addr32[2]^ ip.u.addr32[3]^port;
1098         else
1099                 h=0; /* error */
1100         /* make sure the first bits are influenced by all 32
1101          * (the first log2(SCTP_ADDR_HASH_SIZE) bits should be a mix of all
1102          *  32)*/
1103         h ^= h>>17;
1104         h ^= h>>7;
1105         return h & (SCTP_ADDR_HASH_SIZE-1);
1106 }
1107 #endif /* SCTP_ADDR_HASH */
1108
1109
1110
1111 /** destroy sctp conn hashes. */
1112 void destroy_sctp_con_tracking()
1113 {
1114         int r;
1115         
1116 #ifdef SCTP_HASH_LOCK_PER_BUCKET
1117         if (sctp_con_id_hash)
1118                 for(r=0; r<SCTP_ID_HASH_SIZE; r++)
1119                         lock_destroy(&sctp_con_id_hash[r].lock);
1120         if (sctp_con_assoc_hash)
1121                 for(r=0; r<SCTP_ASSOC_HASH_SIZE; r++)
1122                         lock_destroy(&sctp_con_assoc_hash[r].lock);
1123 #       ifdef SCTP_ADDR_HASH
1124         if (sctp_con_addr_hash)
1125                 for(r=0; r<SCTP_ADDR_HASH_SIZE; r++)
1126                         lock_destroy(&sctp_con_addr_hash[r].lock);
1127 #       endif /* SCTP_ADDR_HASH */
1128 #elif defined SCTP_HASH_LOCK_SET
1129         if (sctp_con_id_h_lock_set){
1130                 lock_set_destroy(sctp_con_id_h_lock_set);
1131                 lock_set_dealloc(sctp_con_id_h_lock_set);
1132                 sctp_con_id_h_lock_set=0;
1133         }
1134         if (sctp_con_assoc_h_lock_set){
1135                 lock_set_destroy(sctp_con_assoc_h_lock_set);
1136                 lock_set_dealloc(sctp_con_assoc_h_lock_set);
1137                 sctp_con_assoc_h_lock_set=0;
1138         }
1139 #       ifdef SCTP_ADDR_HASH
1140         if (sctp_con_addr_h_lock_set){
1141                 lock_set_destroy(sctp_con_addr_h_lock_set);
1142                 lock_set_dealloc(sctp_con_addr_h_lock_set);
1143                 sctp_con_addr_h_lock_set=0;
1144         }
1145 #       endif /* SCTP_ADDR_HASH */
1146 #else /* SCTP_HASH_ONE_LOCK */
1147         if (sctp_con_id_h_lock){
1148                 lock_destroy(sctp_con_id_h_lock);
1149                 lock_dealloc(sctp_con_id_h_lock);
1150                 sctp_con_id_h_lock=0;
1151         }
1152         if (sctp_con_assoc_h_lock){
1153                 lock_destroy(sctp_con_assoc_h_lock);
1154                 lock_dealloc(sctp_con_assoc_h_lock);
1155                 sctp_con_assoc_h_lock=0;
1156         }
1157 #       ifdef SCTP_ADDR_HASH
1158         if (sctp_con_addr_h_lock){
1159                 lock_destroy(sctp_con_addr_h_lock);
1160                 lock_dealloc(sctp_con_addr_h_lock);
1161                 sctp_con_addr_h_lock=0;
1162         }
1163 #       endif /* SCTP_ADDR_HASH */
1164 #endif /* SCTP_HASH_LOCK_PER_BUCKET/SCTP_HASH_LOCK_SET/one lock */
1165         if (sctp_con_id_hash){
1166                 shm_free(sctp_con_id_hash);
1167                 sctp_con_id_hash=0;
1168         }
1169         if (sctp_con_assoc_hash){
1170                 shm_free(sctp_con_assoc_hash);
1171                 sctp_con_assoc_hash=0;
1172         }
1173 #ifdef SCTP_ADDR_HASH
1174         if (sctp_con_addr_hash){
1175                 shm_free(sctp_con_addr_hash);
1176                 sctp_con_addr_hash=0;
1177         }
1178 #endif /* SCTP_ADDR_HASH */
1179         if (sctp_id){
1180                 shm_free(sctp_id);
1181                 sctp_id=0;
1182         }
1183         if (sctp_conn_tracked){
1184                 shm_free(sctp_conn_tracked);
1185                 sctp_conn_tracked=0;
1186         }
1187 }
1188
1189
1190
1191 /** intializaze sctp_conn hashes.
1192   * @return 0 on success, <0 on error
1193   */
1194 int init_sctp_con_tracking()
1195 {
1196         int r, ret;
1197         
1198         sctp_con_id_hash=shm_malloc(SCTP_ID_HASH_SIZE*sizeof(*sctp_con_id_hash));
1199         sctp_con_assoc_hash=shm_malloc(SCTP_ASSOC_HASH_SIZE*
1200                                                                         sizeof(*sctp_con_assoc_hash));
1201 #ifdef SCTP_ADDR_HASH
1202         sctp_con_addr_hash=shm_malloc(SCTP_ADDR_HASH_SIZE*
1203                                                                         sizeof(*sctp_con_addr_hash));
1204 #endif /* SCTP_ADDR_HASH */
1205         sctp_id=shm_malloc(sizeof(*sctp_id));
1206         sctp_conn_tracked=shm_malloc(sizeof(*sctp_conn_tracked));
1207         if (sctp_con_id_hash==0 || sctp_con_assoc_hash==0 ||
1208 #ifdef SCTP_ADDR_HASH
1209                         sctp_con_addr_hash==0 ||
1210 #endif /* SCTP_ADDR_HASH */
1211                         sctp_id==0 || sctp_conn_tracked==0){
1212                 ERR("sctp init: memory allocation error\n");
1213                 ret=E_OUT_OF_MEM;
1214                 goto error;
1215         }
1216         atomic_set(sctp_id, 0);
1217         atomic_set(sctp_conn_tracked, 0);
1218         for (r=0; r<SCTP_ID_HASH_SIZE; r++)
1219                 clist_init(&sctp_con_id_hash[r], l.next_id, l.prev_id);
1220         for (r=0; r<SCTP_ASSOC_HASH_SIZE; r++)
1221                 clist_init(&sctp_con_assoc_hash[r], l.next_assoc, l.prev_assoc);
1222 #ifdef SCTP_ADDR_HASH
1223         for (r=0; r<SCTP_ADDR_HASH_SIZE; r++)
1224                 clist_init(&sctp_con_addr_hash[r], l.next_addr, l.prev_addr);
1225 #endif /* SCTP_ADDR_HASH */
1226 #ifdef SCTP_HASH_LOCK_PER_BUCKET
1227         for (r=0; r<SCTP_ID_HASH_SIZE; r++){
1228                 if (lock_init(&sctp_con_id_hash[r].lock)==0){
1229                         ret=-1;
1230                         ERR("sctp init: failed to initialize locks\n");
1231                         goto error;
1232                 }
1233         }
1234         for (r=0; r<SCTP_ASSOC_HASH_SIZE; r++){
1235                 if (lock_init(&sctp_con_assoc_hash[r].lock)==0){
1236                         ret=-1;
1237                         ERR("sctp init: failed to initialize locks\n");
1238                         goto error;
1239                 }
1240         }
1241 #       ifdef SCTP_ADDR_HASH
1242         for (r=0; r<SCTP_ADDR_HASH_SIZE; r++){
1243                 if (lock_init(&sctp_con_addr_hash[r].lock)==0){
1244                         ret=-1;
1245                         ERR("sctp init: failed to initialize locks\n");
1246                         goto error;
1247                 }
1248         }
1249 #       endif /* SCTP_ADDR_HASH */
1250 #elif defined SCTP_HASH_LOCK_SET
1251         sctp_con_id_h_lock_set=lock_set_alloc(SCTP_ID_HASH_SIZE);
1252         sctp_con_assoc_h_lock_set=lock_set_alloc(SCTP_ASSOC_HASH_SIZE);
1253 #       ifdef SCTP_ADDR_HASH
1254         sctp_con_addr_h_lock_set=lock_set_alloc(SCTP_ADDR_HASH_SIZE);
1255 #       endif /* SCTP_ADDR_HASH */
1256         if (sctp_con_id_h_lock_set==0 || sctp_con_assoc_h_lock_set==0
1257 #       ifdef SCTP_ADDR_HASH
1258                         || sctp_con_addr_h_lock_set==0
1259 #       endif /* SCTP_ADDR_HASH */
1260                         ){
1261                 ret=E_OUT_OF_MEM;
1262                 ERR("sctp_init: failed to alloc lock sets\n");
1263                 goto error;
1264         }
1265         if (lock_set_init(sctp_con_id_h_lock_set)==0){
1266                 lock_set_dealloc(sctp_con_id_h_lock_set);
1267                 sctp_con_id_h_lock_set=0;
1268                 ret=-1;
1269                 ERR("sctp init: failed to initialize lock set\n");
1270                 goto error;
1271         }
1272         if (lock_set_init(sctp_con_assoc_h_lock_set)==0){
1273                 lock_set_dealloc(sctp_con_assoc_h_lock_set);
1274                 sctp_con_assoc_h_lock_set=0;
1275                 ret=-1;
1276                 ERR("sctp init: failed to initialize lock set\n");
1277                 goto error;
1278         }
1279 #       ifdef SCTP_ADDR_HASH
1280         if (lock_set_init(sctp_con_addr_h_lock_set)==0){
1281                 lock_set_dealloc(sctp_con_addr_h_lock_set);
1282                 sctp_con_addr_h_lock_set=0;
1283                 ret=-1;
1284                 ERR("sctp init: failed to initialize lock set\n");
1285                 goto error;
1286         }
1287 #       endif /* SCTP_ADDR_HASH */
1288 #else /* SCTP_HASH_ONE_LOCK */
1289         sctp_con_id_h_lock=lock_alloc();
1290         sctp_con_assoc_h_lock=lock_alloc();
1291 #       ifdef SCTP_ADDR_HASH
1292         sctp_con_addr_h_lock=lock_alloc();
1293 #       endif /* SCTP_ADDR_HASH */
1294         if (sctp_con_id_h_lock==0 || sctp_con_assoc_h_lock==0
1295 #       ifdef SCTP_ADDR_HASH
1296                         || sctp_con_addr_h_lock==0
1297 #       endif /* SCTP_ADDR_HASH */
1298                         ){
1299                 ret=E_OUT_OF_MEM;
1300                 ERR("sctp init: failed to alloc locks\n");
1301                 goto error;
1302         }
1303         if (lock_init(sctp_con_id_h_lock)==0){
1304                 lock_dealloc(sctp_con_id_h_lock);
1305                 sctp_con_id_h_lock=0;
1306                 ret=-1;
1307                 ERR("sctp init: failed to initialize lock\n");
1308                 goto error;
1309         }
1310         if (lock_init(sctp_con_assoc_h_lock)==0){
1311                 lock_dealloc(sctp_con_assoc_h_lock);
1312                 sctp_con_assoc_h_lock=0;
1313                 ret=-1;
1314                 ERR("sctp init: failed to initialize lock\n");
1315                 goto error;
1316         }
1317 #       ifdef SCTP_ADDR_HASH
1318         if (lock_init(sctp_con_addr_h_lock)==0){
1319                 lock_dealloc(sctp_con_addr_h_lock);
1320                 sctp_con_addr_h_lock=0;
1321                 ret=-1;
1322                 ERR("sctp init: failed to initialize lock\n");
1323                 goto error;
1324         }
1325 #       endif /* SCTP_ADDR_HASH */
1326 #endif /* SCTP_HASH_LOCK_PER_BUCKET/SCTP_HASH_LOCK_SET/one lock */
1327         return 0;
1328 error:
1329         destroy_sctp_con_tracking();
1330         return ret;
1331 }
1332
1333
1334
1335 #if 0
1336 /** adds "e" to the hashes, safe locking version.*/
1337 static void sctp_con_add(struct sctp_con_elem* e)
1338 {
1339         unsigned hash;
1340         DBG("sctp_con_add(%p) ( ser id %d, assoc_id %d)\n",
1341                         e, e->con.id, e->con.assoc_id);
1342         
1343         e->l.next_id=e->l.prev_id=0;
1344         e->l.next_assoc=e->l.prev_assoc=0;
1345 #ifdef SCTP_ADDR_HASH
1346         e->l.next_addr=e->l.prev_addr=0;
1347         e->refcnt.val+=3; /* account for the 3 lists */
1348 #else /* SCTP_ADDR_HASH */
1349         e->refcnt.val+=2; /* account for the 2 lists */
1350 #endif /* SCTP_ADDR_HASH */
1351         hash=get_sctp_con_id_hash(e->con.id);
1352         DBG("adding to con id hash %d\n", hash);
1353         LOCK_SCTP_ID_H(hash);
1354                 clist_insert(&sctp_con_id_hash[hash], e, l.next_id, l.prev_id);
1355         UNLOCK_SCTP_ID_H(hash);
1356         hash=get_sctp_con_assoc_hash(e->con.assoc_id);
1357         DBG("adding to assoc_id hash %d\n", hash);
1358         LOCK_SCTP_ASSOC_H(hash);
1359                 clist_insert(&sctp_con_assoc_hash[hash], e,
1360                                                 l.next_assoc, l.prev_assoc);
1361         UNLOCK_SCTP_ASSOC_H(hash);
1362 #ifdef SCTP_ADDR_HASH
1363         hash=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
1364         DBG("adding to addr hash %d\n", hash);
1365         LOCK_SCTP_ADDR_H(hash);
1366                 clist_insert(&sctp_con_addr_hash[hash], e,
1367                                                 l.next_addr, l.prev_addr);
1368         UNLOCK_SCTP_ADDR_H(hash);
1369 #endif /* SCTP_ADDR_HASH */
1370         atomic_inc(sctp_conn_tracked);
1371 }
1372 #endif
1373
1374
1375
1376 /** helper internal del elem function, the id hash must be locked.
1377   * WARNING: the id hash(h) _must_ be locked (LOCK_SCTP_ID_H(h)).
1378   * @param h - id hash
1379   * @param e - sctp_con_elem to delete (from all the hashes)
1380   * @return 0 if the id hash was unlocked, 1 if it's still locked */
1381 inline static int _sctp_con_del_id_locked(unsigned h, struct sctp_con_elem* e)
1382 {
1383         unsigned assoc_id_h;
1384         int deref; /* delayed de-reference counter */
1385         int locked;
1386 #ifdef SCTP_ADDR_HASH
1387         unsigned addr_h;
1388 #endif /* SCTP_ADDR_HASH */
1389         
1390         locked=1;
1391         clist_rm(e, l.next_id, l.prev_id);
1392         e->l.next_id=e->l.prev_id=0; /* mark it as id unhashed */
1393         /* delay atomic dereference, so that we'll perform only one
1394            atomic op. even for multiple derefs. It also has the
1395            nice side-effect that the entry will be guaranteed to be
1396            referenced until we perform the delayed deref. at the end,
1397            so we don't need to keep some lock to prevent somebody from
1398            deleting the entry from under us */
1399         deref=1; /* removed from one list =>  deref once */
1400         /* remove it from the assoc hash if needed */
1401         if (likely(e->l.next_assoc)){
1402                 UNLOCK_SCTP_ID_H(h);
1403                 locked=0; /* no longer id-locked */
1404                 /* we haven't dec. refcnt, so it's still safe to use e */
1405                 assoc_id_h=get_sctp_con_assoc_hash(e->con.assoc_id);
1406                 LOCK_SCTP_ASSOC_H(assoc_id_h);
1407                         /* make sure nobody removed it in the meantime */
1408                         if (likely(e->l.next_assoc)){
1409                                 clist_rm(e, l.next_assoc, l.prev_assoc);
1410                                 e->l.next_assoc=e->l.prev_assoc=0; /* mark it as removed */
1411                                 deref++; /* rm'ed from the assoc list => inc. delayed deref. */
1412                         }
1413                 UNLOCK_SCTP_ASSOC_H(assoc_id_h);
1414         }
1415 #ifdef SCTP_ADDR_HASH
1416         /* remove it from the addr. hash if needed */
1417         if (likely(e->l.next_addr)){
1418                 if (unlikely(locked)){
1419                         UNLOCK_SCTP_ID_H(h);
1420                         locked=0; /* no longer id-locked */
1421                 }
1422                 addr_h=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
1423                 LOCK_SCTP_ADDR_H(addr_h);
1424                         /* make sure nobody removed it in the meantime */
1425                         if (likely(e->l.next_addr)){
1426                                 clist_rm(e, l.next_addr, l.prev_addr);
1427                                 e->l.next_addr=e->l.prev_addr=0; /* mark it as removed */
1428                                 deref++; /* rm'ed from the addr list => inc. delayed deref. */
1429                         }
1430                 UNLOCK_SCTP_ADDR_H(addr_h);
1431         }
1432 #endif /* SCTP_ADDR_HASH */
1433         
1434         /* performed delayed de-reference */
1435         if (atomic_add(&e->refcnt, -deref)==0){
1436                 atomic_dec(sctp_conn_tracked);
1437                 shm_free(e);
1438         }
1439         else
1440                 DBG("del assoc post-deref (kept): ser id %d, assoc_id %d,"
1441                         " post-refcnt %d, deref %d, post-tracked %d\n",
1442                         e->con.id, e->con.assoc_id, atomic_get(&e->refcnt), deref,
1443                         atomic_get(sctp_conn_tracked));
1444         return locked;
1445 }
1446
1447
1448
1449 /** helper internal del elem function, the assoc hash must be locked.
1450   * WARNING: the assoc hash(h) _must_ be locked (LOCK_SCTP_ASSOC_H(h)).
1451   * @param h - assoc hash
1452   * @param e - sctp_con_elem to delete (from all the hashes)
1453   * @return 0 if the assoc hash was unlocked, 1 if it's still locked */
1454 inline static int _sctp_con_del_assoc_locked(unsigned h,
1455                                                                                                 struct sctp_con_elem* e)
1456 {
1457         unsigned id_hash;
1458         int deref; /* delayed de-reference counter */
1459         int locked;
1460 #ifdef SCTP_ADDR_HASH
1461         unsigned addr_h;
1462 #endif /* SCTP_ADDR_HASH */
1463         
1464         locked=1;
1465         clist_rm(e, l.next_assoc, l.prev_assoc);
1466         e->l.next_assoc=e->l.prev_assoc=0; /* mark it as assoc unhashed */
1467         /* delay atomic dereference, so that we'll perform only one
1468            atomic op. even for multiple derefs. It also has the
1469            nice side-effect that the entry will be guaranteed to be
1470            referenced until we perform the delayed deref. at the end,
1471            so we don't need to keep some lock to prevent somebody from
1472            deleting the entry from under us */
1473         deref=1; /* removed from one list =>  deref once */
1474         /* remove it from the id hash if needed */
1475         if (likely(e->l.next_id)){
1476                 UNLOCK_SCTP_ASSOC_H(h);
1477                 locked=0; /* no longer assoc-hash-locked */
1478                 /* we have a ref. to it so it's still safe to use e */
1479                 id_hash=get_sctp_con_id_hash(e->con.id);
1480                 LOCK_SCTP_ID_H(id_hash);
1481                         /* make sure nobody removed it in the meantime */
1482                         if (likely(e->l.next_id)){
1483                                 clist_rm(e, l.next_id, l.prev_id);
1484                                 e->l.next_id=e->l.prev_id=0; /* mark it as removed */
1485                                 deref++; /* rm'ed from the id list => inc. delayed deref. */
1486                         }
1487                 UNLOCK_SCTP_ID_H(id_hash);
1488         }
1489 #ifdef SCTP_ADDR_HASH
1490         /* remove it from the addr. hash if needed */
1491         if (likely(e->l.next_addr)){
1492                 if (unlikely(locked)){
1493                         UNLOCK_SCTP_ASSOC_H(h);
1494                         locked=0; /* no longer id-locked */
1495                 }
1496                 addr_h=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
1497                 LOCK_SCTP_ADDR_H(addr_h);
1498                         /* make sure nobody removed it in the meantime */
1499                         if (likely(e->l.next_addr)){
1500                                 clist_rm(e, l.next_addr, l.prev_addr);
1501                                 e->l.next_addr=e->l.prev_addr=0; /* mark it as removed */
1502                                 deref++; /* rm'ed from the addr list => inc. delayed deref. */
1503                         }
1504                 UNLOCK_SCTP_ADDR_H(addr_h);
1505         }
1506 #endif /* SCTP_ADDR_HASH */
1507         if (atomic_add(&e->refcnt, -deref)==0){
1508                 atomic_dec(sctp_conn_tracked);
1509                 shm_free(e);
1510         }
1511         else
1512                 DBG("del assoc post-deref (kept): ser id %d, assoc_id %d,"
1513                                 " post-refcnt %d, deref %d, post-tracked %d\n",
1514                                 e->con.id, e->con.assoc_id, atomic_get(&e->refcnt), deref,
1515                                 atomic_get(sctp_conn_tracked));
1516         return locked;
1517 }
1518
1519
1520
1521 #ifdef SCTP_ADDR_HASH
1522 /** helper internal del elem function, the addr hash must be locked.
1523   * WARNING: the addr hash(h) _must_ be locked (LOCK_SCTP_ADDR_H(h)).
1524   * @param h - addr hash
1525   * @param e - sctp_con_elem to delete (from all the hashes)
1526   * @return 0 if the addr hash was unlocked, 1 if it's still locked */
1527 inline static int _sctp_con_del_addr_locked(unsigned h,
1528                                                                                                 struct sctp_con_elem* e)
1529 {
1530         unsigned id_hash;
1531         unsigned assoc_id_h;
1532         int deref; /* delayed de-reference counter */
1533         int locked;
1534         
1535         locked=1;
1536         clist_rm(e, l.next_addr, l.prev_addr);
1537         e->l.next_addr=e->l.prev_addr=0; /* mark it as addr unhashed */
1538         /* delay atomic dereference, so that we'll perform only one
1539            atomic op. even for multiple derefs. It also has the
1540            nice side-effect that the entry will be guaranteed to be
1541            referenced until we perform the delayed deref. at the end,
1542            so we don't need to keep some lock to prevent somebody from
1543            deleting the entry from under us */
1544         deref=1; /* removed from one list =>  deref once */
1545         /* remove it from the id hash if needed */
1546         if (likely(e->l.next_id)){
1547                 UNLOCK_SCTP_ADDR_H(h);
1548                 locked=0; /* no longer addr-hash-locked */
1549                 /* we have a ref. to it so it's still safe to use e */
1550                 id_hash=get_sctp_con_id_hash(e->con.id);
1551                 LOCK_SCTP_ID_H(id_hash);
1552                         /* make sure nobody removed it in the meantime */
1553                         if (likely(e->l.next_id)){
1554                                 clist_rm(e, l.next_id, l.prev_id);
1555                                 e->l.next_id=e->l.prev_id=0; /* mark it as removed */
1556                                 deref++; /* rm'ed from the id list => inc. delayed deref. */
1557                         }
1558                 UNLOCK_SCTP_ID_H(id_hash);
1559         }
1560         /* remove it from the assoc hash if needed */
1561         if (likely(e->l.next_assoc)){
1562                 if (locked){
1563                         UNLOCK_SCTP_ADDR_H(h);
1564                         locked=0; /* no longer addr-hash-locked */
1565                 }
1566                 /* we haven't dec. refcnt, so it's still safe to use e */
1567                 assoc_id_h=get_sctp_con_assoc_hash(e->con.assoc_id);
1568                 LOCK_SCTP_ASSOC_H(assoc_id_h);
1569                         /* make sure nobody removed it in the meantime */
1570                         if (likely(e->l.next_assoc)){
1571                                 clist_rm(e, l.next_assoc, l.prev_assoc);
1572                                 e->l.next_assoc=e->l.prev_assoc=0; /* mark it as removed */
1573                                 deref++; /* rm'ed from the assoc list => inc. delayed deref. */
1574                         }
1575                 UNLOCK_SCTP_ASSOC_H(assoc_id_h);
1576         }
1577         if (atomic_add(&e->refcnt, -deref)==0){
1578                 atomic_dec(sctp_conn_tracked);
1579                 shm_free(e);
1580         }
1581         else
1582                 DBG("del assoc post-deref (kept): ser id %d, assoc_id %d,"
1583                                 " post-refcnt %d, deref %d, post-tracked %d\n",
1584                                 e->con.id, e->con.assoc_id, atomic_get(&e->refcnt), deref,
1585                                 atomic_get(sctp_conn_tracked));
1586         return locked;
1587 }
1588 #endif /* SCTP_ADDR_HASH */
1589
1590
1591
1592 /** delete all tracked associations entries.
1593  */
1594 void sctp_con_tracking_flush()
1595 {
1596         unsigned h;
1597         struct sctp_con_elem* e;
1598         struct sctp_con_elem* tmp;
1599         
1600         for (h=0; h<SCTP_ID_HASH_SIZE; h++){
1601 again:
1602                 LOCK_SCTP_ID_H(h);
1603                         clist_foreach_safe(&sctp_con_id_hash[h], e, tmp, l.next_id) {
1604                                 if (_sctp_con_del_id_locked(h, e)==0){
1605                                         /* unlocked, need to lock again and restart the list */
1606                                         goto again;
1607                                 }
1608                         }
1609                 UNLOCK_SCTP_ID_H(h);
1610         }
1611 }
1612
1613
1614
1615 /** using id, get the corresponding sctp assoc & socket. 
1616  *  @param id - ser unique assoc id
1617  *  @param si  - result parameter, filled with the socket info on success
1618  *  @param remote - result parameter, filled with the address and port
1619  *  @param del - if 1 delete the entry,
1620  *  @return assoc_id (!=0) on success & sets si, 0 on not found
1621  * si and remote will not be touched on failure.
1622  *
1623  */
1624 int sctp_con_get_assoc(unsigned int id, struct socket_info** si, 
1625                                                                 union sockaddr_union *remote, int del)
1626 {
1627         unsigned h;
1628         ticks_t now; 
1629         struct sctp_con_elem* e;
1630         struct sctp_con_elem* tmp;
1631         int ret;
1632         
1633         ret=0;
1634         now=get_ticks_raw();
1635         h=get_sctp_con_id_hash(id);
1636 #if 0
1637 again:
1638 #endif
1639         LOCK_SCTP_ID_H(h);
1640                 clist_foreach_safe(&sctp_con_id_hash[h], e, tmp, l.next_id){
1641                         if(e->con.id==id){
1642                                 ret=e->con.assoc_id;
1643                                 *si=e->con.si;
1644                                 *remote=e->con.remote;
1645                                 if (del){
1646                                         if (_sctp_con_del_id_locked(h, e)==0)
1647                                                 goto skip_unlock;
1648                                 }else
1649                                         e->con.expire=now +
1650                                                                 S_TO_TICKS(cfg_get(sctp, sctp_cfg, autoclose));
1651                                 break;
1652                         }
1653 #if 0
1654                         else if (TICKS_LT(e->con.expire, now)){
1655                                 WARN("sctp con: found expired assoc %d, id %d (%d s ago)\n",
1656                                                 e->con.assoc_id, e->con.id,
1657                                                 TICKS_TO_S(now-e->con.expire));
1658                                 if (_sctp_con_del_id_locked(h, e)==0)
1659                                         goto again; /* if unlocked need to restart the list */
1660                         }
1661 #endif
1662                 }
1663         UNLOCK_SCTP_ID_H(h);
1664 skip_unlock:
1665         return ret;
1666 }
1667
1668
1669
1670 /** using the assoc_id, remote addr. & socket, get the corresp. internal id.
1671  *  @param assoc_id - sctp assoc id
1672  *  @param si  - socket on which the packet was received
1673  *  @param del - if 1 delete the entry,
1674  *  @return assoc_id (!=0) on success, 0 on not found
1675  */
1676 int sctp_con_get_id(unsigned int assoc_id, union sockaddr_union* remote,
1677                                         struct socket_info* si, int del)
1678 {
1679         unsigned h;
1680         ticks_t now; 
1681         struct sctp_con_elem* e;
1682         struct sctp_con_elem* tmp;
1683         int ret;
1684         
1685         ret=0;
1686         now=get_ticks_raw();
1687         h=get_sctp_con_assoc_hash(assoc_id);
1688 #if 0
1689 again:
1690 #endif
1691         LOCK_SCTP_ASSOC_H(h);
1692                 clist_foreach_safe(&sctp_con_assoc_hash[h], e, tmp, l.next_assoc){
1693                         if(e->con.assoc_id==assoc_id && e->con.si==si &&
1694                                         su_cmp(remote, &e->con.remote)){
1695                                 ret=e->con.id;
1696                                 if (del){
1697                                         if (_sctp_con_del_assoc_locked(h, e)==0)
1698                                                 goto skip_unlock;
1699                                 }else
1700                                         e->con.expire=now +
1701                                                                 S_TO_TICKS(cfg_get(sctp, sctp_cfg, autoclose));
1702                                 break;
1703                         }
1704 #if 0
1705                         else if (TICKS_LT(e->con.expire, now)){
1706                                 WARN("sctp con: found expired assoc %d, id %d (%d s ago)\n",
1707                                                 e->con.assoc_id, e->con.id,
1708                                                 TICKS_TO_S(now-e->con.expire));
1709                                 if (_sctp_con_del_assoc_locked(h, e)==0)
1710                                         goto again; /* if unlocked need to restart the list */
1711                         }
1712 #endif
1713                 }
1714         UNLOCK_SCTP_ASSOC_H(h);
1715 skip_unlock:
1716         return ret;
1717 }
1718
1719
1720
1721 #ifdef SCTP_ADDR_HASH
1722 /** using the dest. & source socket, get the corresponding id and assoc_id 
1723  *  @param remote   - peer address & port
1724  *  @param si       - local source socket
1725  *  @param assoc_id - result, filled with the sctp assoc_id
1726  *  @param del - if 1 delete the entry,
1727  *  @return ser id (!=0) on success, 0 on not found
1728  */
1729 int sctp_con_addr_get_id_assoc(union sockaddr_union* remote,
1730                                                                 struct socket_info* si,
1731                                                                 int* assoc_id, int del)
1732 {
1733         unsigned h;
1734         ticks_t now; 
1735         struct sctp_con_elem* e;
1736         struct sctp_con_elem* tmp;
1737         int ret;
1738         
1739         ret=0;
1740         *assoc_id=0;
1741         now=get_ticks_raw();
1742         h=get_sctp_con_addr_hash(remote, si);
1743 again:
1744         LOCK_SCTP_ADDR_H(h);
1745                 clist_foreach_safe(&sctp_con_addr_hash[h], e, tmp, l.next_addr){
1746                         if(su_cmp(remote, &e->con.remote) && e->con.si==si){
1747                                 ret=e->con.id;
1748                                 *assoc_id=e->con.assoc_id;
1749                                 if (del){
1750                                         if (_sctp_con_del_addr_locked(h, e)==0)
1751                                                 goto skip_unlock;
1752                                 }else
1753                                         e->con.expire=now +
1754                                                                 S_TO_TICKS(cfg_get(sctp, sctp_cfg, autoclose));
1755                                 break;
1756                         }
1757 #if 0
1758                         else if (TICKS_LT(e->con.expire, now)){
1759                                 WARN("sctp con: found expired assoc %d, id %d (%d s ago)\n",
1760                                                 e->con.assoc_id, e->con.id,
1761                                                 TICKS_TO_S(now-e->con.expire));
1762                                 if (_sctp_con_del_addr_locked(h, e)==0)
1763                                         goto again; /* if unlocked need to restart the list */
1764                         }
1765 #endif
1766                 }
1767         UNLOCK_SCTP_ADDR_H(h);
1768 skip_unlock:
1769         return ret;
1770 }
1771 #endif /* SCTP_ADDR_HASH */
1772
1773
1774
1775 /** del con tracking for (assod_id, si).
1776  * @return 0 on success, -1 on error (not found)
1777  */
1778 #define sctp_con_del_assoc(assoc_id, si) \
1779         (-(sctp_con_get_id((assoc_id), (si), 1)==0))
1780
1781
1782
1783 /** create a new sctp con elem.
1784   * @param id - ser connection id
1785   * @param assoc_id - sctp assoc id
1786   * @param si - corresp. socket
1787   * @param remote - remote side
1788   * @return pointer to shm allocated sctp_con_elem on success, 0 on error
1789   */
1790 struct sctp_con_elem* sctp_con_new(unsigned id, unsigned assoc_id, 
1791                                                                         struct socket_info* si,
1792                                                                         union sockaddr_union* remote)
1793 {
1794         struct sctp_con_elem* e;
1795         
1796         e=shm_malloc(sizeof(*e));
1797         if (unlikely(e==0))
1798                 goto error;
1799         e->l.next_id=e->l.prev_id=0;
1800         e->l.next_assoc=e->l.prev_assoc=0;
1801         atomic_set(&e->refcnt, 0);
1802         e->con.id=id;
1803         e->con.assoc_id=assoc_id;
1804         e->con.si=si;
1805         e->con.flags=0;
1806         if (likely(remote))
1807                 e->con.remote=*remote;
1808         else
1809                 memset(&e->con.remote, 0, sizeof(e->con.remote));
1810         e->con.start=get_ticks_raw();
1811         e->con.expire=e->con.start +
1812                                 S_TO_TICKS(cfg_get(sctp, sctp_cfg, autoclose));
1813         return e;
1814 error:
1815         return 0;
1816 }
1817
1818
1819
1820 /** handles every ev on sctp assoc_id.
1821   * @return ser id on success (!=0) or 0 on not found/error
1822   */
1823 static int sctp_con_track(int assoc_id, struct socket_info* si,
1824                                                         union sockaddr_union* remote, int ev)
1825 {
1826         int id;
1827         unsigned hash;
1828         unsigned assoc_hash;
1829         struct sctp_con_elem* e;
1830         struct sctp_con_elem* tmp;
1831         
1832         id=0;
1833         DBG("sctp_con_track(%d, %p, %d) \n", assoc_id, si, ev);
1834         
1835         /* search for (assoc_id, si) */
1836         assoc_hash=get_sctp_con_assoc_hash(assoc_id);
1837         LOCK_SCTP_ASSOC_H(assoc_hash);
1838                 clist_foreach_safe(&sctp_con_assoc_hash[assoc_hash], e, tmp,
1839                                                                 l.next_assoc){
1840                         /* we need to use the remote side address, because at least
1841                            on linux assoc_id are immediately reused (even if sctp
1842                            autoclose is off) and so it's possible that the association
1843                            id we saved is already closed and assigned to another
1844                            association by the time we search for it) */
1845                         if(e->con.assoc_id==assoc_id && e->con.si==si &&
1846                                         su_cmp(remote, &e->con.remote)){
1847                                 if (ev==SCTP_CON_DOWN_SEEN){
1848                                         if (e->con.flags & SCTP_CON_UP_SEEN){
1849                                                 /* DOWN after UP => delete */
1850                                                 id=e->con.id;
1851                                                 /* do delete */
1852                                                 if (_sctp_con_del_assoc_locked(assoc_hash, e)==0)
1853                                                         goto found; /* skip unlock */
1854                                         }else{
1855                                                 /* DOWN after DOWN => error
1856                                                    DOWN after RCV w/ no UP -> not possible
1857                                                     since we never create a tracking entry on RCV
1858                                                         only */
1859                                                 BUG("unexpected flags: %x for assoc_id %d, id %d"
1860                                                                 ", sctp con %p\n", e->con.flags, assoc_id,
1861                                                                 e->con.id, e);
1862                                                 /* do delete */
1863                                                 if (_sctp_con_del_assoc_locked(assoc_hash, e)==0)
1864                                                         goto found; /* skip unlock */
1865                                         }
1866                                 }else if (ev==SCTP_CON_RCV_SEEN){
1867                                         /* RCV after UP or DOWN => just mark RCV as seen */
1868                                         id=e->con.id;
1869                                         e->con.flags |= SCTP_CON_RCV_SEEN;
1870                                 }else{
1871                                         /* SCTP_CON_UP */
1872                                         if (e->con.flags & SCTP_CON_DOWN_SEEN){
1873                                                 /* UP after DOWN => delete */
1874                                                 id=e->con.id;
1875                                                 /* do delete */
1876                                                 if (_sctp_con_del_assoc_locked(assoc_hash, e)==0)
1877                                                         goto found; /* skip unlock */
1878                                         }else{
1879                                                 /* UP after UP or after RCVD => BUG */
1880                                                 BUG("connection with same assoc_id (%d) already"
1881                                                                 " present, flags %x\n",
1882                                                                 assoc_id, e->con.flags);
1883                                         }
1884                                 }
1885                                 UNLOCK_SCTP_ASSOC_H(assoc_hash);
1886                                 goto found;
1887                         }
1888                 }
1889                 /* not found */
1890                 if (unlikely(ev!=SCTP_CON_RCV_SEEN)){
1891                         /* UP or DOWN and no tracking entry => create new tracking entry
1892                            for both of them (because we can have a re-ordered DOWN before
1893                            the UP) */
1894 again:
1895                                 id=atomic_add(sctp_id, 1);
1896                                 if (unlikely(id==0)){
1897                                         /* overflow  and 0 is not a valid id */
1898                                         goto again;
1899                                 }
1900                                 e=sctp_con_new(id, assoc_id, si, remote);
1901                                 if (likely(e)){
1902                                         e->con.flags=ev;
1903                                         e->l.next_id=e->l.prev_id=0;
1904                                         e->l.next_assoc=e->l.prev_assoc=0;
1905 #ifdef SCTP_ADDR_HASH
1906                                         e->l.next_addr=e->l.prev_addr=0;
1907                                         e->refcnt.val+=3; /* account for the 3 lists */
1908 #else /* SCTP_ADDR_HASH */
1909                                         e->refcnt.val+=2; /* account for the 2 lists */
1910 #endif /* SCTP_ADDR_HASH */
1911                                         /* already locked */
1912                                         clist_insert(&sctp_con_assoc_hash[assoc_hash], e,
1913                                                                         l.next_assoc, l.prev_assoc);
1914                                         hash=get_sctp_con_id_hash(e->con.id);
1915                                         LOCK_SCTP_ID_H(hash);
1916                                                 clist_insert(&sctp_con_id_hash[hash], e,
1917                                                                         l.next_id, l.prev_id);
1918                                         UNLOCK_SCTP_ID_H(hash);
1919 #ifdef SCTP_ADDR_HASH
1920                                         hash=get_sctp_con_addr_hash(&e->con.remote, e->con.si);
1921                                         LOCK_SCTP_ADDR_H(hash);
1922                                                 clist_insert(&sctp_con_addr_hash[hash], e,
1923                                                                         l.next_addr, l.prev_addr);
1924                                         UNLOCK_SCTP_ADDR_H(hash);
1925 #endif /* SCTP_ADDR_HASH */
1926                                         atomic_inc(sctp_conn_tracked);
1927                                 }
1928                 } /* else not found and RCV -> ignore
1929                          We cannot create a new entry because we don't know when to
1930                          delete it (we can have UP DOWN RCV which would result in a
1931                          tracking entry living forever). This means that if we receive
1932                          a msg. on an assoc. before it's UP notification we won't know
1933                          the id for connection reuse, but since happens very rarely it's
1934                          an acceptable tradeoff */
1935         UNLOCK_SCTP_ASSOC_H(assoc_hash);
1936         if (unlikely(e==0)){
1937                 ERR("memory allocation failure\n");
1938                 goto error;
1939         }
1940 found:
1941         return id;
1942 error:
1943         return 0;
1944 }
1945
1946
1947
1948 #else /* SCTP_CONN_REUSE */
1949 void sctp_con_tracking_flush() {}
1950 #endif /* SCTP_CONN_REUSE */
1951
1952
1953 int init_sctp()
1954 {
1955         int ret;
1956         
1957         ret=0;
1958         if (INIT_SCTP_STATS()!=0){
1959                 ERR("sctp init: failed to intialize sctp stats\n");
1960                 goto error;
1961         }
1962         /* sctp options must be initialized before  calling this function */
1963         sctp_conn_no=shm_malloc(sizeof(*sctp_conn_tracked));
1964         if ( sctp_conn_no==0){
1965                 ERR("sctp init: memory allocation error\n");
1966                 ret=E_OUT_OF_MEM;
1967                 goto error;
1968         }
1969         atomic_set(sctp_conn_no, 0);
1970 #ifdef SCTP_CONN_REUSE
1971         return init_sctp_con_tracking();
1972 #endif
1973 error:
1974         return ret;
1975 }
1976
1977
1978
1979 void destroy_sctp()
1980 {
1981         if (sctp_conn_no){
1982                 shm_free(sctp_conn_no);
1983                 sctp_conn_no=0;
1984         }
1985 #ifdef SCTP_CONN_REUSE
1986         destroy_sctp_con_tracking();
1987 #endif
1988         DESTROY_SCTP_STATS();
1989 }
1990
1991
1992
1993 static int sctp_msg_send_ext(struct dest_info* dst, char* buf, unsigned len,
1994                                                 struct sctp_sndrcvinfo* sndrcv_info);
1995 #define SCTP_SEND_FIRST_ASSOCID 1  /* sctp_raw_send flag */
1996 static int sctp_raw_send(int socket, char* buf, unsigned len,
1997                                                 union sockaddr_union* to,
1998                                                 struct sctp_sndrcvinfo* sndrcv_info,
1999                                                 int flags);
2000
2001
2002
2003 /* debugging: return a string name for SCTP_ASSOC_CHANGE state */
2004 static char* sctp_assoc_change_state2s(short int state)
2005 {
2006         char* s;
2007         
2008         switch(state){
2009                 case SCTP_COMM_UP:
2010                         s="SCTP_COMM_UP";
2011                         break;
2012                 case SCTP_COMM_LOST:
2013                         s="SCTP_COMM_LOST";
2014                         break;
2015                 case SCTP_RESTART:
2016                         s="SCTP_RESTART";
2017                         break;
2018                 case SCTP_SHUTDOWN_COMP:
2019                         s="SCTP_SHUTDOWN_COMP";
2020                         break;
2021                 case SCTP_CANT_STR_ASSOC:
2022                         s="SCTP_CANT_STR_ASSOC";
2023                         break;
2024                 default:
2025                         s="UNKNOWN";
2026                         break;
2027         };
2028         return s;
2029 }
2030
2031
2032
2033 /* debugging: return a string name for a SCTP_PEER_ADDR_CHANGE state */
2034 static char* sctp_paddr_change_state2s(unsigned int state)
2035 {
2036         char* s;
2037         
2038         switch (state){
2039                 case SCTP_ADDR_AVAILABLE:
2040                         s="SCTP_ADDR_AVAILABLE";
2041                         break;
2042                 case SCTP_ADDR_UNREACHABLE:
2043                         s="SCTP_ADDR_UNREACHABLE";
2044                         break;
2045                 case SCTP_ADDR_REMOVED:
2046                         s="SCTP_ADDR_REMOVED";
2047                         break;
2048                 case SCTP_ADDR_ADDED:
2049                         s="SCTP_ADDR_ADDED";
2050                         break;
2051                 case SCTP_ADDR_MADE_PRIM:
2052                         s="SCTP_ADDR_MADE_PRIM";
2053                         break;
2054         /* not supported by lksctp 1.0.6 
2055                 case SCTP_ADDR_CONFIRMED:
2056                         s="SCTP_ADDR_CONFIRMED";
2057                         break;
2058         */
2059                 default:
2060                         s="UNKNOWN";
2061                         break;
2062         }
2063         return s;
2064 }
2065
2066
2067
2068 /* handle SCTP_SEND_FAILED notifications: if packet marked for retries
2069  * retry the send (with 0 assoc_id)
2070  * returns 0 on success, -1 on failure
2071  */
2072 static int sctp_handle_send_failed(struct socket_info* si,
2073                                                                         union sockaddr_union* su,
2074                                                                         char* buf, unsigned len)
2075 {
2076         union sctp_notification* snp;
2077         struct sctp_sndrcvinfo sinfo;
2078         struct dest_info dst;
2079         char* data;
2080         unsigned data_len;
2081         int retries;
2082         int ret;
2083 #ifdef HAVE_SCTP_SNDRCVINFO_PR_POLICY
2084         int send_ttl;
2085 #endif
2086         
2087         ret=-1;
2088         SCTP_STATS_SEND_FAILED();
2089         snp=(union sctp_notification*) buf;
2090         retries=snp->sn_send_failed.ssf_info.sinfo_context;
2091         
2092         /* don't retry on explicit remote error
2093          * (unfortunately we can't be more picky than this, we get no 
2094          * indication in the SEND_FAILED notification for other error
2095          * reasons (e.g. ABORT received, INIT timeout a.s.o)
2096          */
2097         if (retries && (snp->sn_send_failed.ssf_error==0)) {
2098                 DBG("sctp: RETRY-ing (%d)\n", retries);
2099                 SCTP_STATS_SEND_FORCE_RETRY();
2100                 retries--;
2101                 data=(char*)snp->sn_send_failed.ssf_data;
2102                 data_len=snp->sn_send_failed.ssf_length - 
2103                                         sizeof(struct sctp_send_failed);
2104                 
2105                 memset(&sinfo, 0, sizeof(sinfo));
2106                 sinfo.sinfo_flags=SCTP_UNORDERED;
2107 #ifdef HAVE_SCTP_SNDRCVINFO_PR_POLICY
2108                 if ((send_ttl=cfg_get(sctp, sctp_cfg, send_ttl))){
2109                         sinfo.sinfo_pr_policy=SCTP_PR_SCTP_TTL;
2110                         sinfo.sinfo_pr_value=send_ttl;
2111                 }else
2112                         sinfo.info_pr_policy=SCTP_PR_SCTP_NONE;
2113 #else
2114                 sinfo.sinfo_timetolive=cfg_get(sctp, sctp_cfg, send_ttl);
2115 #endif
2116                 sinfo.sinfo_context=retries;
2117                 
2118                 dst.to=*su;
2119                 dst.send_sock=si;
2120                 dst.id=0;
2121                 dst.proto=PROTO_SCTP;
2122 #ifdef USE_COMP
2123                 dst.comp=COMP_NONE;
2124 #endif
2125                 
2126                 ret=sctp_msg_send_ext(&dst, data, data_len, &sinfo);
2127         }
2128 #ifdef USE_DST_BLACKLIST
2129          else if (cfg_get(core, core_cfg, use_dst_blacklist) &&
2130                                         cfg_get(sctp, sctp_cfg, send_retries)) {
2131                 /* blacklist only if send_retries is on, if off we blacklist
2132                    from SCTP_ASSOC_CHANGE: SCTP_COMM_LOST/SCTP_CANT_STR_ASSOC
2133                    which is better (because we can tell connect errors from send
2134                    errors and we blacklist a failed dst only once) */
2135                 dst_blacklist_su(BLST_ERR_SEND, PROTO_SCTP, su, 0);
2136         }
2137 #endif /* USE_DST_BLACKLIST */
2138         
2139         return (ret>0)?0:ret;
2140 }
2141
2142
2143
2144 /* handle SCTP_ASOC_CHANGE notifications: map ser global sctp ids
2145  * to kernel asoc_ids. The global ids are needed because the kernel ones
2146  * might get reused after a close and so they are not unique for ser's
2147  * lifetime. We need a unique id to match replies to the association on
2148  * which we received the corresponding request (so that we can send them
2149  * back on the same asoc & socket if still opened).
2150  * returns 0 on success, -1 on failure
2151  */
2152 static int sctp_handle_assoc_change(struct socket_info* si,
2153                                                                         union sockaddr_union* su,
2154                                                                         union sctp_notification* snp
2155                                                                         )
2156 {
2157         int ret;
2158         int state;
2159         int assoc_id;
2160         struct sctp_sndrcvinfo sinfo;
2161         struct ip_addr ip; /* used only on error, for debugging */
2162         
2163         state=snp->sn_assoc_change.sac_state;
2164         assoc_id=snp->sn_assoc_change.sac_assoc_id;
2165         
2166         ret=-1;
2167         switch(state){
2168                 case SCTP_COMM_UP:
2169                         SCTP_STATS_ESTABLISHED();
2170                         atomic_inc(sctp_conn_no);
2171 #ifdef SCTP_CONN_REUSE
2172                         /* new connection, track it */
2173                         if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2174                                         sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
2175 #if 0
2176 again:
2177                         id=atomic_add(sctp_id, 1);
2178                         if (unlikely(id==0)){
2179                                 /* overflow  and 0 is not a valid id */
2180                                 goto again;
2181                         }
2182                         e=sctp_con_new(id, assoc_id, si, su);
2183                         if (unlikely(e==0)){
2184                                 ERR("memory allocation failure\n");
2185                         }else{
2186                                 sctp_con_add(e);
2187                                 ret=0;
2188                         }
2189 #endif
2190 #endif /* SCTP_CONN_REUSE */
2191                         if (unlikely((unsigned)atomic_get(sctp_conn_no) >
2192                                                         (unsigned)cfg_get(sctp, sctp_cfg, max_assocs))){
2193                                 /* maximum assoc exceeded => we'll have to immediately 
2194                                    close it */
2195                                 memset(&sinfo, 0, sizeof(sinfo));
2196                                 sinfo.sinfo_flags=SCTP_UNORDERED | SCTP_ABORT;
2197                                 sinfo.sinfo_assoc_id=assoc_id;
2198                                 ret=sctp_raw_send(si->socket, ABORT_REASON_MAX_ASSOCS,
2199                                                                                         sizeof(ABORT_REASON_MAX_ASSOCS)-1,
2200                                                                                         su, &sinfo, 0);
2201                                 if (ret<0){
2202                                         su2ip_addr(&ip, su);
2203                                         WARN("failed to ABORT new sctp association %d (%s:%d):"
2204                                                         " %s (%d)\n", assoc_id, ip_addr2a(&ip),
2205                                                         su_getport(su), strerror(errno), errno);
2206                                 }else{
2207                                         SCTP_STATS_LOCAL_REJECT();
2208                                 }
2209                         }
2210                         break;
2211                 case SCTP_COMM_LOST:
2212                         SCTP_STATS_COMM_LOST();
2213 #ifdef USE_DST_BLACKLIST
2214                         /* blacklist only if send_retries is turned off (if on we don't
2215                            know here if we did retry or we are at the first error) */
2216                         if (cfg_get(core, core_cfg, use_dst_blacklist) &&
2217                                         (cfg_get(sctp, sctp_cfg, send_retries)==0))
2218                                                 dst_blacklist_su(BLST_ERR_SEND, PROTO_SCTP, su, 0);
2219 #endif /* USE_DST_BLACKLIST */
2220                         /* no break */
2221                 case SCTP_SHUTDOWN_COMP:
2222                         atomic_dec(sctp_conn_no);
2223 #ifdef SCTP_CONN_REUSE
2224                         /* connection down*/
2225                         if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2226                                 sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
2227 #if 0
2228                         if (unlikely(sctp_con_del_assoc(assoc_id, si)!=0))
2229                                 WARN("sctp con: tried to remove inexistent connection\n");
2230                         else
2231                                 ret=0;
2232 #endif
2233 #endif /* SCTP_CONN_REUSE */
2234                         break;
2235                 case SCTP_RESTART:
2236                         /* do nothing on restart */
2237                         break;
2238                 case SCTP_CANT_STR_ASSOC:
2239                         SCTP_STATS_CONNECT_FAILED();
2240                         /* do nothing when failing to start an assoc
2241                           (in this case we never see SCTP_COMM_UP so we never 
2242                           track the assoc) */
2243 #ifdef USE_DST_BLACKLIST
2244                         /* blacklist only if send_retries is turned off (if on we don't 
2245                            know here if we did retry or we are at the first error) */
2246                         if (cfg_get(core, core_cfg, use_dst_blacklist) &&
2247                                         (cfg_get(sctp, sctp_cfg, send_retries)==0))
2248                                                 dst_blacklist_su(BLST_ERR_CONNECT, PROTO_SCTP, su, 0);
2249 #endif /* USE_DST_BLACKLIST */
2250                         break;
2251                 default:
2252                         break;
2253         }
2254         return ret;
2255 }
2256
2257
2258
2259 static int sctp_handle_notification(struct socket_info* si,
2260                                                                         union sockaddr_union* su,
2261                                                                         char* buf, unsigned len)
2262 {
2263         union sctp_notification* snp;
2264         char su_buf[SU2A_MAX_STR_SIZE];
2265         
2266         #define SNOT DBG
2267         #define ERR_LEN_TOO_SMALL(length, val, bind_addr, from_su, text) \
2268                 if (unlikely((length)<(val))){\
2269                         SNOT("ERROR: sctp notification from %s on %.*s:%d: " \
2270                                                 text " too short (%d bytes instead of %d bytes)\n", \
2271                                                 su2a((from_su), sizeof(*(from_su))), \
2272                                                 (bind_addr)->name.len, (bind_addr)->name.s, \
2273                                                 (bind_addr)->port_no, (int)(length), (int)(val)); \
2274                         goto error; \
2275                 }
2276
2277         if (len < sizeof(snp->sn_header)){
2278                 LOG(L_ERR, "ERROR: sctp_handle_notification: invalid length %d "
2279                                         "on %.*s:%d, from %s\n",
2280                                         len, si->name.len, si->name.s, si->port_no,
2281                                         su2a(su, sizeof(*su)));
2282                 goto error;
2283         }
2284         snp=(union sctp_notification*) buf;
2285         switch(snp->sn_header.sn_type){
2286                 case SCTP_REMOTE_ERROR:
2287                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_remote_error), si, su,
2288                                                                 "SCTP_REMOTE_ERROR");
2289                         SCTP_EV_REMOTE_ERROR(&si->address, si->port_no, su, 
2290                                                                         ntohs(snp->sn_remote_error.sre_error) );
2291                         SNOT("sctp notification from %s on %.*s:%d: SCTP_REMOTE_ERROR:"
2292                                         " %d, len %d\n, assoc_id %d",
2293                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2294                                         si->port_no,
2295                                         ntohs(snp->sn_remote_error.sre_error),
2296                                         ntohs(snp->sn_remote_error.sre_length),
2297                                         snp->sn_remote_error.sre_assoc_id
2298                                 );
2299                         break;
2300                 case SCTP_SEND_FAILED:
2301                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_send_failed), si, su,
2302                                                                 "SCTP_SEND_FAILED");
2303                         SCTP_EV_SEND_FAILED(&si->address, si->port_no, su, 
2304                                                                         snp->sn_send_failed.ssf_error);
2305                         SNOT("sctp notification from %s on %.*s:%d: SCTP_SEND_FAILED:"
2306                                         " error %d, assoc_id %d, flags %x\n",
2307                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2308                                         si->port_no, snp->sn_send_failed.ssf_error,
2309                                         snp->sn_send_failed.ssf_assoc_id,
2310                                         snp->sn_send_failed.ssf_flags);
2311                         sctp_handle_send_failed(si, su, buf, len);
2312                         break;
2313                 case SCTP_PEER_ADDR_CHANGE:
2314                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_paddr_change), si, su,
2315                                                                 "SCTP_PEER_ADDR_CHANGE");
2316                         SCTP_EV_PEER_ADDR_CHANGE(&si->address, si->port_no, su, 
2317                                         sctp_paddr_change_state2s(snp->sn_paddr_change.spc_state),
2318                                         snp->sn_paddr_change.spc_state,
2319                                         &snp->sn_paddr_change.spc_aaddr);
2320                         strcpy(su_buf, su2a((union sockaddr_union*)
2321                                                                         &snp->sn_paddr_change.spc_aaddr, 
2322                                                                         sizeof(snp->sn_paddr_change.spc_aaddr)));
2323                         SNOT("sctp notification from %s on %.*s:%d: SCTP_PEER_ADDR_CHANGE"
2324                                         ": %s: %s: assoc_id %d \n",
2325                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2326                                         si->port_no, su_buf,
2327                                         sctp_paddr_change_state2s(snp->sn_paddr_change.spc_state),
2328                                         snp->sn_paddr_change.spc_assoc_id
2329                                         );
2330                         break;
2331                 case SCTP_SHUTDOWN_EVENT:
2332                         SCTP_STATS_REMOTE_SHUTDOWN();
2333                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_shutdown_event), si, su,
2334                                                                 "SCTP_SHUTDOWN_EVENT");
2335                         SCTP_EV_SHUTDOWN_EVENT(&si->address, si->port_no, su);
2336                         SNOT("sctp notification from %s on %.*s:%d: SCTP_SHUTDOWN_EVENT:"
2337                                         " assoc_id %d\n",
2338                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2339                                         si->port_no, snp->sn_shutdown_event.sse_assoc_id);
2340                         break;
2341                 case SCTP_ASSOC_CHANGE:
2342                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_assoc_change), si, su,
2343                                                                 "SCTP_ASSOC_CHANGE");
2344                         SCTP_EV_ASSOC_CHANGE(&si->address, si->port_no, su, 
2345                                         sctp_assoc_change_state2s(snp->sn_assoc_change.sac_state),
2346                                         snp->sn_assoc_change.sac_state);
2347                         SNOT("sctp notification from %s on %.*s:%d: SCTP_ASSOC_CHANGE"
2348                                         ": %s: assoc_id %d, ostreams %d, istreams %d\n",
2349                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2350                                         si->port_no,
2351                                         sctp_assoc_change_state2s(snp->sn_assoc_change.sac_state),
2352                                         snp->sn_assoc_change.sac_assoc_id,
2353                                         snp->sn_assoc_change.sac_outbound_streams,
2354                                         snp->sn_assoc_change.sac_inbound_streams
2355                                         );
2356                         sctp_handle_assoc_change(si, su, snp);
2357                         break;
2358 #ifdef SCTP_ADAPTION_INDICATION
2359                 case SCTP_ADAPTION_INDICATION:
2360                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_adaption_event), si, su,
2361                                                                 "SCTP_ADAPTION_INDICATION");
2362                         SNOT("sctp notification from %s on %.*s:%d: "
2363                                         "SCTP_ADAPTION_INDICATION \n",
2364                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2365                                         si->port_no);
2366                         break;
2367 #endif /* SCTP_ADAPTION_INDICATION */
2368                 case SCTP_PARTIAL_DELIVERY_EVENT:
2369                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_pdapi_event), si, su,
2370                                                                 "SCTP_PARTIAL_DELIVERY_EVENT");
2371                         ERR("sctp notification from %s on %.*s:%d: "
2372                                         "SCTP_PARTIAL_DELIVERY_EVENT not supported: %d %s,"
2373                                         "assoc_id %d\n",
2374                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2375                                         si->port_no, snp->sn_pdapi_event.pdapi_indication,
2376                                         (snp->sn_pdapi_event.pdapi_indication==
2377                                                 SCTP_PARTIAL_DELIVERY_ABORTED)? " PD ABORTED":"",
2378                                         snp->sn_pdapi_event.pdapi_assoc_id);
2379                         break;
2380 #ifdef SCTP_SENDER_DRY_EVENT /* new, not yet supported */
2381                 case SCTP_SENDER_DRY_EVENT:
2382                         ERR_LEN_TOO_SMALL(len, sizeof(struct sctp_sender_dry_event),
2383                                                                 si, su, "SCTP_SENDER_DRY_EVENT");
2384                         SCTP_EV_REMOTE_ERROR(&si->address, si->port_no, su);
2385                         SNOT("sctp notification from %s on %.*s:%d: "
2386                                         "SCTP_SENDER_DRY_EVENT on %d\n",
2387                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2388                                         si->port_no, snp->sn_sender_dry_event.sender_dry_assoc_id);
2389                         break;
2390 #endif /* SCTP_SENDER_DRY_EVENT */
2391                 default:
2392                         SNOT("sctp notification from %s on %.*s:%d: UNKNOWN (%d)\n",
2393                                         su2a(su, sizeof(*su)), si->name.len, si->name.s,
2394                                         si->port_no, snp->sn_header.sn_type);
2395         }
2396         return 0;
2397 error:
2398         return -1;
2399         #undef ERR_LEN_TOO_SMALL
2400 }
2401
2402
2403
2404 int sctp_rcv_loop()
2405 {
2406         unsigned len;
2407         static char buf [BUF_SIZE+1];
2408         char *tmp;
2409         struct receive_info ri;
2410         struct sctp_sndrcvinfo* sinfo;
2411         struct msghdr msg;
2412         struct iovec iov[1];
2413         struct cmsghdr* cmsg;
2414         /* use a larger buffer then needed in case some other ancillary info
2415          * is enabled */
2416         char cbuf[CMSG_SPACE(sizeof(*sinfo))+CMSG_SPACE(1024)];
2417
2418         
2419         ri.bind_address=bind_address; /* this will not change */
2420         ri.dst_port=bind_address->port_no;
2421         ri.dst_ip=bind_address->address;
2422         ri.proto=PROTO_SCTP;
2423         ri.proto_reserved2=0;
2424         
2425         iov[0].iov_base=buf;
2426         iov[0].iov_len=BUF_SIZE;
2427         msg.msg_iov=iov;
2428         msg.msg_iovlen=1;
2429         msg.msg_flags=0;
2430         
2431
2432         /* initialize the config framework */
2433         if (cfg_child_init()) goto error;
2434         
2435         for(;;){
2436                 msg.msg_name=&ri.src_su.s;
2437                 msg.msg_namelen=sockaddru_len(bind_address->su);
2438                 msg.msg_control=cbuf;
2439                 msg.msg_controllen=sizeof(cbuf);
2440                 sinfo=0;
2441
2442                 len=recvmsg(bind_address->socket, &msg, 0);
2443                 if (len==-1){
2444                         if (errno==EAGAIN){
2445                                 DBG("sctp_rcv_loop: EAGAIN on sctp socket\n");
2446                                 continue;
2447                         }
2448                         LOG(L_ERR, "ERROR: sctp_rcv_loop: sctp_recvmsg on %d (%p):"
2449                                                 "[%d] %s\n", bind_address->socket, bind_address,
2450                                                 errno, strerror(errno));
2451                         if ((errno==EINTR)||(errno==EWOULDBLOCK)|| (errno==ECONNREFUSED))
2452                                 continue; /* goto skip;*/
2453                         else goto error;
2454                 }
2455                 if (unlikely(msg.msg_flags & MSG_NOTIFICATION)){
2456                         /* intercept useful notifications */
2457                         sctp_handle_notification(bind_address, &ri.src_su, buf, len);
2458                         continue;
2459                 }else if (unlikely(!(msg.msg_flags & MSG_EOR))){
2460                         LOG(L_ERR, "ERROR: sctp_rcv_loop: partial delivery not"
2461                                                 "supported\n");
2462                         continue;
2463                 }
2464                 
2465                 su2ip_addr(&ri.src_ip, &ri.src_su);
2466                 ri.src_port=su_getport(&ri.src_su);
2467                 
2468                 /* get ancillary data */
2469                 for (cmsg=CMSG_FIRSTHDR(&msg); cmsg; cmsg=CMSG_NXTHDR(&msg, cmsg)){
2470                         if (likely((cmsg->cmsg_level==IPPROTO_SCTP) &&
2471                                                 ((cmsg->cmsg_type==SCTP_SNDRCV)
2472 #ifdef SCTP_EXT
2473                                                  || (cmsg->cmsg_type==SCTP_EXTRCV)
2474 #endif
2475                                                 ) && (cmsg->cmsg_len>=CMSG_LEN(sizeof(*sinfo)))) ){
2476                                 sinfo=(struct sctp_sndrcvinfo*)CMSG_DATA(cmsg);
2477                                 DBG("sctp recv: message from %s:%d stream %d  ppid %x"
2478                                                 " flags %x%s tsn %u" " cumtsn %u assoc_id %d\n",
2479                                                 ip_addr2a(&ri.src_ip), ri.src_port,
2480                                                 sinfo->sinfo_stream, sinfo->sinfo_ppid,
2481                                                 sinfo->sinfo_flags,
2482                                                 (sinfo->sinfo_flags&SCTP_UNORDERED)?
2483                                                         " (SCTP_UNORDERED)":"",
2484                                                 sinfo->sinfo_tsn, sinfo->sinfo_cumtsn, 
2485                                                 sinfo->sinfo_assoc_id);
2486                                 break;
2487                         }
2488                 }
2489                 /* we  0-term the messages for debugging */
2490                 buf[len]=0; /* no need to save the previous char */
2491
2492                 /* sanity checks */
2493                 if (len<MIN_SCTP_PACKET) {
2494                         tmp=ip_addr2a(&ri.src_ip);
2495                         DBG("sctp_rcv_loop: probing packet received from %s:%d\n",
2496                                         tmp, ri.src_port);
2497                         continue;
2498                 }
2499                 if (ri.src_port==0){
2500                         tmp=ip_addr2a(&ri.src_ip);
2501                         LOG(L_INFO, "sctp_rcv_loop: dropping 0 port packet from %s:0\n",
2502                                                 tmp);
2503                         continue;
2504                 }
2505 #ifdef USE_COMP
2506                 ri.comp=COMP_NONE;
2507 #endif
2508                 /* update the local config */
2509                 cfg_update();
2510 #ifdef SCTP_CONN_REUSE
2511                 if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking) && sinfo)){
2512                         ri.proto_reserved1 = sctp_con_track(sinfo->sinfo_assoc_id,
2513                                                                                                 ri.bind_address, 
2514                                                                                                 &ri.src_su,
2515                                                                                                 SCTP_CON_RCV_SEEN);
2516                         /* debugging */
2517                         if (unlikely(ri.proto_reserved1==0))
2518                                 DBG("no tracked assoc. found for assoc_id %d, from %s\n",
2519                                                 sinfo->sinfo_assoc_id, 
2520                                                 su2a(&ri.src_su, sizeof(ri.src_su)));
2521 #if 0
2522                         ri.proto_reserved1=
2523                                 sctp_con_get_id(sinfo->sinfo_assoc_id, ri.bind_address, 0);
2524 #endif
2525                 }else
2526                         ri.proto_reserved1=0;
2527 #else /* SCTP_CONN_REUSE */
2528                 ri.proto_received1=0;
2529 #endif /* SCTP_CONN_REUSE */
2530                 receive_msg(buf, len, &ri);
2531         }
2532 error:
2533         return -1;
2534 }
2535
2536
2537
2538 /** low level sctp non-blocking send.
2539  * @param socket - sctp socket to send on.
2540  * @param buf   - data.
2541  * @param len   - lenght of the data.
2542  * @param to    - destination in ser sockaddr_union format.
2543  * @param sndrcv_info - sctp_sndrcvinfo structure pointer, pre-filled.
2544  * @param flags - can have one of the following values (or'ed):
2545  *                SCTP_SEND_FIRST_ASSOCID - try to send first to assoc_id
2546  *                and only if that fails use "to".
2547  * @return the numbers of bytes sent on success (>=0) and -1 on error.
2548  * On error errno is set too.
2549  */
2550 static int sctp_raw_send(int socket, char* buf, unsigned len,
2551                                                 union sockaddr_union* to,
2552                                                 struct sctp_sndrcvinfo* sndrcv_info,
2553                                                 int flags)
2554 {
2555         int n;
2556         int tolen;
2557         int try_assoc_id;
2558 #if 0
2559         struct ip_addr ip; /* used only on error, for debugging */
2560 #endif
2561         struct msghdr msg;
2562         struct iovec iov[1];
2563         struct sctp_sndrcvinfo* sinfo;
2564         struct cmsghdr* cmsg;
2565         /* make sure msg_control will point to properly aligned data */
2566         union {
2567                 struct cmsghdr cm;
2568                 char cbuf[CMSG_SPACE(sizeof(*sinfo))];
2569         }ctrl_un;
2570         
2571         iov[0].iov_base=buf;
2572         iov[0].iov_len=len;
2573         msg.msg_iov=iov;
2574         msg.msg_iovlen=1;
2575         msg.msg_flags=0; /* not used on send (use instead sinfo_flags) */
2576         msg.msg_control=ctrl_un.cbuf;
2577         msg.msg_controllen=sizeof(ctrl_un.cbuf);
2578         cmsg=CMSG_FIRSTHDR(&msg);
2579         cmsg->cmsg_level=IPPROTO_SCTP;
2580         cmsg->cmsg_type=SCTP_SNDRCV;
2581         cmsg->cmsg_len=CMSG_LEN(sizeof(*sinfo));
2582         sinfo=(struct sctp_sndrcvinfo*)CMSG_DATA(cmsg);
2583         *sinfo=*sndrcv_info;
2584         /* some systems need msg_controllen set to the actual size and not
2585          * something bigger (e.g. openbsd) */
2586         msg.msg_controllen=cmsg->cmsg_len;
2587         try_assoc_id= ((flags & SCTP_SEND_FIRST_ASSOCID) && sinfo->sinfo_assoc_id);
2588         /* if assoc_id is set it means we want to send on association assoc_id
2589            and only if it's not opened any longer use the addresses */
2590         if (try_assoc_id){
2591                 /* on linux msg->name has priority over assoc_id. To try first assoc_id
2592                  * and then "to", one has to call first sendmsg() with msg->name==0 and
2593                  * sinfo->assoc_id set. If it returns EPIPE => association is no longer
2594                  * open => call again sendmsg() this time with msg->name!=0.
2595                  * on freebsd assoc_id has priority over msg->name and moreover the
2596                  * send falls back automatically to the address if the assoc_id is
2597                  * closed, so a single call to sendmsg(msg->name, sinfo->assoc_id ) is
2598                  * enough.  If one tries calling with msg->name==0 and the association
2599                  * is no longer open send will return ENOENT.
2600                  * on solaris it seems one must always use a dst address (assoc_id
2601                  * will be ignored).
2602                  */
2603 #ifdef __OS_linux
2604                 msg.msg_name=0;
2605                 msg.msg_namelen=0;
2606 #elif defined __OS_freebsd
2607                 tolen=sockaddru_len(*to);
2608                 msg.msg_name=&to->s;
2609                 msg.msg_namelen=tolen;
2610 #else /* __OS_* */
2611                 /* fallback for solaris and others, sent back to
2612                   the address recorded (not exactly what we want, but there's
2613                   no way to fallback to "to") */
2614                 tolen=sockaddru_len(*to);
2615                 msg.msg_name=&to->s;
2616                 msg.msg_namelen=tolen;
2617 #endif /* __OS_* */
2618         }else{
2619                 tolen=sockaddru_len(*to);
2620                 msg.msg_name=&to->s;
2621                 msg.msg_namelen=tolen;
2622         }
2623         
2624 again:
2625         n=sendmsg(socket, &msg, MSG_DONTWAIT);
2626         if (n==-1){
2627 #ifdef __OS_linux
2628                 if ((errno==EPIPE) && try_assoc_id){
2629                         /* try again, this time with null assoc_id and non-null msg.name */
2630                         DBG("sctp raw sendmsg: assoc already closed (EPIPE), retrying with"
2631                                         " assoc_id=0\n");
2632                         tolen=sockaddru_len(*to);
2633                         msg.msg_name=&to->s;
2634                         msg.msg_namelen=tolen;
2635                         sinfo->sinfo_assoc_id=0;
2636                         try_assoc_id=0;
2637                         goto again;
2638                 }
2639 #elif defined __OS_freebsd
2640                 if ((errno==ENOENT)){
2641                         /* it didn't work, no retrying */
2642                         WARN("unexpected sendmsg() failure (ENOENT),"
2643                                         " assoc_id %d\n", sinfo->sinfo_assoc_id);
2644                 }
2645 #else /* __OS_* */
2646                 if ((errno==ENOENT || errno==EPIPE) && try_assoc_id){
2647                         /* in case the sctp stack prioritises assoc_id over msg->name,
2648                            try again with 0 assoc_id and msg->name set to "to" */
2649                         WARN("unexpected ENOENT or EPIPE (assoc_id %d),"
2650                                         "trying automatic recovery... (please report along with"
2651                                         "your OS version)\n", sinfo->sinfo_assoc_id);
2652                         tolen=sockaddru_len(*to);
2653                         msg.msg_name=&to->s;
2654                         msg.msg_namelen=tolen;
2655                         sinfo->sinfo_assoc_id=0;
2656                         try_assoc_id=0;
2657                         goto again;
2658                 }
2659 #endif /* __OS_* */
2660 #if 0
2661                 if (errno==EINTR) goto again;
2662                 su2ip_addr(&ip, to);
2663                 LOG(L_ERR, "ERROR: sctp_raw_send: sendmsg(sock,%p,%d,0,%s:%d,...):"
2664                                 " %s(%d)\n", buf, len, ip_addr2a(&ip), su_getport(to),
2665                                 strerror(errno), errno);
2666                 if (errno==EINVAL) {
2667                         LOG(L_CRIT,"CRITICAL: invalid sendmsg parameters\n"
2668                         "one possible reason is the server is bound to localhost and\n"
2669                         "attempts to send to the net\n");
2670                 }else if (errno==EAGAIN || errno==EWOULDBLOCK){
2671                         SCTP_STATS_SENDQ_FULL();
2672                         LOG(L_ERR, "ERROR: sctp_msg_send: failed to send, send buffers"
2673                                                 " full\n");
2674                 }
2675 #endif
2676         }
2677         return n;
2678 }
2679
2680
2681
2682 /* send buf:len over sctp to dst using sndrcv_info (uses send_sock,
2683  * to and id from dest_info)
2684  * returns the numbers of bytes sent on success (>=0) and -1 on error
2685  */
2686 static int sctp_msg_send_ext(struct dest_info* dst, char* buf, unsigned len,
2687                                                 struct sctp_sndrcvinfo* sndrcv_info)
2688 {
2689         int n;
2690         int tolen;
2691         struct ip_addr ip; /* used only on error, for debugging */
2692         struct msghdr msg;
2693         struct iovec iov[1];
2694         struct socket_info* si;
2695         struct sctp_sndrcvinfo* sinfo;
2696         struct cmsghdr* cmsg;
2697         /* make sure msg_control will point to properly aligned data */
2698         union {
2699                 struct cmsghdr cm;
2700                 char cbuf[CMSG_SPACE(sizeof(*sinfo))];
2701         }ctrl_un;
2702 #ifdef SCTP_CONN_REUSE
2703         int assoc_id;
2704         union sockaddr_union to;
2705 #ifdef SCTP_ADDR_HASH
2706         int tmp_id, tmp_assoc_id;
2707 #endif /* SCTP_ADDR_HASH */
2708 #endif /* SCTP_CONN_REUSE */
2709         
2710         iov[0].iov_base=buf;
2711         iov[0].iov_len=len;
2712         msg.msg_iov=iov;
2713         msg.msg_iovlen=1;
2714         msg.msg_flags=0; /* not used on send (use instead sinfo_flags) */
2715         msg.msg_control=ctrl_un.cbuf;
2716         msg.msg_controllen=sizeof(ctrl_un.cbuf);
2717         cmsg=CMSG_FIRSTHDR(&msg);
2718         cmsg->cmsg_level=IPPROTO_SCTP;
2719         cmsg->cmsg_type=SCTP_SNDRCV;
2720         cmsg->cmsg_len=CMSG_LEN(sizeof(*sinfo));
2721         sinfo=(struct sctp_sndrcvinfo*)CMSG_DATA(cmsg);
2722         *sinfo=*sndrcv_info;
2723         /* some systems need msg_controllen set to the actual size and not
2724          * something bigger (e.g. openbsd) */
2725         msg.msg_controllen=cmsg->cmsg_len;
2726         si=dst->send_sock;
2727 #ifdef SCTP_CONN_REUSE
2728         /* if dst->id is set it means we want to send on association with
2729            ser id dst->id if still opened and only if closed use dst->to */
2730         assoc_id=0;
2731         if ((dst->id) && cfg_get(sctp, sctp_cfg, assoc_reuse) &&
2732                         cfg_get(sctp, sctp_cfg, assoc_tracking) &&
2733                         (assoc_id=sctp_con_get_assoc(dst->id, &si, &to, 0))){
2734                 DBG("sctp: sending on sctp assoc_id %d (ser id %d)\n",
2735                                 assoc_id, dst->id);
2736                 sinfo->sinfo_assoc_id=assoc_id;
2737                 /* on linux msg->name has priority over assoc_id. To try first assoc_id
2738                  * and then dst, one has to call first sendmsg() with msg->name==0 and
2739                  * sinfo->assoc_id set. If it returns EPIPE => association is no longer
2740                  * open => call again sendmsg() this time with msg->name!=0.
2741                  * on freebsd assoc_id has priority over msg->name and moreover the
2742                  * send falls back automatically to the address if the assoc_id is
2743                  * closed, so a single call to sendmsg(msg->name, sinfo->assoc_id ) is
2744                  * enough.  If one tries calling with msg->name==0 and the association
2745                  * is no longer open send will return ENOENT.
2746                  * on solaris it seems one must always use a dst address (assoc_id
2747                  * will be ignored).
2748                  */
2749 #ifdef __OS_linux
2750                 DBG("sctp: linux: trying with 0 msg_name\n");
2751                 msg.msg_name=0;
2752                 msg.msg_namelen=0;
2753 #elif defined __OS_freebsd
2754                 tolen=sockaddru_len(dst->to);
2755                 msg.msg_name=&dst->to.s;
2756                 msg.msg_namelen=tolen;
2757 #else /* __OS_* */
2758                 /* fallback for solaris and others, sent back to
2759                   the address recorded (not exactly what we want, but there's 
2760                   no way to fallback to dst->to) */
2761                 tolen=sockaddru_len(dst->to);
2762                 msg.msg_name=&dst->to.s;
2763                 msg.msg_namelen=tolen;
2764 #endif /* __OS_* */
2765         }else{
2766 #ifdef SCTP_ADDR_HASH
2767                 /* update timeout for the assoc identified  by (dst->to, dst->si) */
2768                 if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking))){
2769                         tmp_id=sctp_con_addr_get_id_assoc(&dst->to, dst->send_sock,
2770                                                                                                 &tmp_assoc_id, 0);
2771                         DBG("sctp send: timeout updated ser id %d, sctp assoc_id %d\n",
2772                                         tmp_id, tmp_assoc_id);
2773                         if (tmp_id==0 /* not tracked/found */ &&
2774                                         (unsigned)atomic_get(sctp_conn_tracked) >=
2775                                                 (unsigned)cfg_get(sctp, sctp_cfg, max_assocs)){
2776                                 ERR("maximum number of sctp associations exceeded\n");
2777                                 goto error;
2778                         }
2779                 }
2780 #endif /* SCTP_ADDR_HASH */
2781                 tolen=sockaddru_len(dst->to);
2782                 msg.msg_name=&dst->to.s;
2783                 msg.msg_namelen=tolen;
2784         }
2785 #else /* SCTP_CONN_REUSE */
2786         tolen=sockaddru_len(dst->to);
2787         msg.msg_name=&dst->to.s;
2788         msg.msg_namelen=tolen;
2789 #endif /* SCTP_CONN_REUSE */
2790
2791 again:
2792         n=sendmsg(si->socket, &msg, MSG_DONTWAIT);
2793         if (n==-1){
2794 #ifdef SCTP_CONN_REUSE
2795 #ifdef __OS_linux
2796                 if ((errno==EPIPE) && assoc_id){
2797                         /* try again, this time with null assoc_id and non-null msg.name */
2798                         DBG("sctp sendmsg: assoc already closed (EPIPE), retrying with"
2799                                         " assoc_id=0\n");
2800                         tolen=sockaddru_len(dst->to);
2801                         msg.msg_name=&dst->to.s;
2802                         msg.msg_namelen=tolen;
2803                         sinfo->sinfo_assoc_id=0;
2804                         goto again;
2805                 }
2806 #elif defined __OS_freebsd
2807                 if ((errno==ENOENT)){
2808                         /* it didn't work, no retrying */
2809                         WARN("sctp sendmsg: unexpected sendmsg() failure (ENOENT),"
2810                                         " assoc_id %d\n", assoc_id);
2811                 }
2812 #else /* __OS_* */
2813                 if ((errno==ENOENT || errno==EPIPE) && assoc_id){
2814                         /* in case the sctp stack prioritises assoc_id over msg->name,
2815                            try again with 0 assoc_id and msg->name set to dst->to */
2816                         WARN("sctp sendmsg: unexpected ENOENT or EPIPE (assoc_id %d),"
2817                                         "trying automatic recovery... (please report along with"
2818                                         "your OS version)\n", assoc_id);
2819                         tolen=sockaddru_len(dst->to);
2820                         msg.msg_name=&dst->to.s;
2821                         msg.msg_namelen=tolen;
2822                         sinfo->sinfo_assoc_id=0;
2823                         goto again;
2824                 }
2825 #endif /* __OS_* */
2826 #endif /* SCTP_CONN_REUSE */
2827                 su2ip_addr(&ip, &dst->to);
2828                 LOG(L_ERR, "ERROR: sctp_msg_send: sendmsg(sock,%p,%d,0,%s:%d,...):"
2829                                 " %s(%d)\n", buf, len, ip_addr2a(&ip), su_getport(&dst->to),
2830                                 strerror(errno), errno);
2831                 if (errno==EINTR) goto again;
2832                 if (errno==EINVAL) {
2833                         LOG(L_CRIT,"CRITICAL: invalid sendmsg parameters\n"
2834                         "one possible reason is the server is bound to localhost and\n"
2835                         "attempts to send to the net\n");
2836                 }else if (errno==EAGAIN || errno==EWOULDBLOCK){
2837                         SCTP_STATS_SENDQ_FULL();
2838                         LOG(L_ERR, "ERROR: sctp_msg_send: failed to send, send buffers"
2839                                                 " full\n");
2840                 }
2841         }
2842         return n;
2843 #ifdef SCTP_CONN_REUSE
2844 #ifdef SCTP_ADDR_HASH
2845 error:
2846         return -1;
2847 #endif /* SCTP_ADDR_HASH */
2848 #endif /* SCTP_CONN_REUSE */
2849 }
2850
2851
2852
2853 /* wrapper around sctp_msg_send_ext():
2854  * send buf:len over udp to dst (uses only the to, send_sock and id members
2855  * from dst)
2856  * returns the numbers of bytes sent on success (>=0) and -1 on error
2857  */
2858 int sctp_msg_send(struct dest_info* dst, char* buf, unsigned len)
2859 {
2860         struct sctp_sndrcvinfo sinfo;
2861 #ifdef HAVE_SCTP_SNDRCVINFO_PR_POLICY
2862         int send_ttl;
2863 #endif
2864         
2865         memset(&sinfo, 0, sizeof(sinfo));
2866         sinfo.sinfo_flags=SCTP_UNORDERED;
2867 #ifdef HAVE_SCTP_SNDRCVINFO_PR_POLICY
2868         if ((send_ttl=cfg_get(sctp, sctp_cfg, send_ttl))){
2869                 sinfo.sinfo_pr_policy=SCTP_PR_SCTP_TTL;
2870                 sinfo.sinfo_pr_value=send_ttl;
2871         }else
2872                 sinfo->sinfo_pr_policy=SCTP_PR_SCTP_NONE;
2873 #else
2874                 sinfo.sinfo_timetolive=cfg_get(sctp, sctp_cfg, send_ttl);
2875 #endif
2876         sinfo.sinfo_context=cfg_get(sctp, sctp_cfg, send_retries);
2877         return sctp_msg_send_ext(dst, buf, len, &sinfo);
2878 }
2879
2880
2881
2882 /** generic sctp info (basic stats).*/
2883 void sctp_get_info(struct sctp_gen_info* i)
2884 {
2885         if (i){
2886                 i->sctp_connections_no=atomic_get(sctp_conn_no);
2887 #ifdef SCTP_CONN_REUSE
2888                 if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2889                         i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
2890                 else
2891                         i->sctp_tracked_no=-1;
2892 #else /* SCTP_CONN_REUSE */
2893                 i->sctp_tracked_no=-1;
2894 #endif /* SCTP_CONN_REUSE */
2895                 i->sctp_total_connections=atomic_get(sctp_id);
2896         }
2897 }
2898
2899
2900 #endif /* USE_SCTP */