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