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