b6d7e3636050e008e483e41df8fc6a9e54e5903b
[sip-router] / sctp_options.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 options
20  */
21 /*
22  * History:
23  * --------
24  *  2008-08-07  initial version (andrei)
25  *  2009-05-26  runtime cfg support (andrei)
26  */
27
28 #include <string.h>
29 #include <sys/types.h>
30 #ifdef USE_SCTP
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/sctp.h>
36 #endif /* USE_SCTP */
37 #include <errno.h>
38
39 #include "sctp_options.h"
40 #include "dprint.h"
41 #include "cfg/cfg.h"
42 #include "socket_info.h"
43 #include "sctp_server.h"
44
45 struct cfg_group_sctp sctp_default_cfg;
46
47
48
49 #ifdef USE_SCTP
50
51
52 static int set_autoclose(void* cfg_h, str* gname, str* name, void** val);
53 static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val);
54 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val);
55 static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val);
56 static int set_srto_max(void* cfg_h, str* gname, str* name, void** val);
57 static int set_srto_min(void* cfg_h, str* gname, str* name, void** val);
58 static int set_asocmaxrxt(void* cfg_h, str* gname, str* name, void** val);
59 static int set_sinit_max_attempts(void* cfg_h, str* gname, str* name,
60                                                                                 void** val);
61 static int set_sinit_max_init_timeo(void* cfg_h, str* gname, str* name,
62                                                                                 void** val);
63 static int set_hbinterval(void* cfg_h, str* gname, str* name, void** val);
64 static int set_pathmaxrxt(void* cfg_h, str* gname, str* name, void** val);
65 static int set_sack_freq(void* cfg_h, str* gname, str* name, void** val);
66 static int set_sack_delay(void* cfg_h, str* gname, str* name, void** val);
67 static int set_max_burst(void* cfg_h, str* gname, str* name, void** val);
68
69 /** cfg_group_sctp description (for the config framework). */
70 static cfg_def_t sctp_cfg_def[] = {
71         /*   name        , type |input type| chg type, min, max, fixup, proc. cbk.
72               description */
73         { "socket_rcvbuf", CFG_VAR_INT| CFG_READONLY, 512, 102400, 0, 0,
74                 "socket receive buffer size (read-only)" },
75         { "socket_sndbuf", CFG_VAR_INT| CFG_READONLY, 512, 102400, 0, 0,
76                 "socket send buffer size (read-only)" },
77         { "autoclose", CFG_VAR_INT| CFG_ATOMIC, 1, 1<<30, set_autoclose, 0,
78                 "seconds before closing and idle connection (must be non-zero)" },
79         { "send_ttl", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, 0, 0,
80                 "milliseconds before aborting a send" },
81         { "send_retries", CFG_VAR_INT| CFG_ATOMIC, 0, MAX_SCTP_SEND_RETRIES, 0, 0,
82                 "re-send attempts on failure" },
83         { "assoc_tracking", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_tracking, 0,
84                 "connection/association tracking (see also assoc_reuse)" },
85         { "assoc_reuse", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_reuse, 0,
86                 "connection/association reuse (for now used only for replies)"
87                 ", depends on assoc_tracking being set"},
88         { "max_assocs", CFG_VAR_INT| CFG_ATOMIC, 0, 0, 0, 0,
89                 "maximum allowed open associations (-1 = disable, "
90                         "as many as allowed by the OS)"},
91         { "srto_initial", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_initial, 0,
92                 "initial value of the retr. timeout, used in RTO calculations,"
93                         " in msecs" },
94         { "srto_max", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_max, 0,
95                 "maximum value of the retransmission timeout (RTO), in msecs" },
96         { "srto_min", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_min, 0,
97                 "minimum value of the retransmission timeout (RTO), in msecs" },
98         { "asocmaxrxt", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_asocmaxrxt, 0,
99                 "maximum retransmission attempts per association" },
100         { "init_max_attempts", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10,
101                 set_sinit_max_attempts, 0, "max INIT retransmission attempts" },
102         { "init_max_timeo", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10,
103                 set_sinit_max_init_timeo, 0,
104                 "max INIT retransmission timeout (RTO max for INIT), in msecs" },
105         { "hbinterval", CFG_VAR_INT| CFG_ATOMIC, 0, 0, set_hbinterval, 0,
106                 "heartbeat interval in msecs" },
107         { "pathmaxrxt", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_pathmaxrxt, 0,
108                 "maximum retransmission attempts per path" },
109         { "sack_delay", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_sack_delay, 0,
110                 "time since the last received packet before sending a SACK, in msecs"},
111         { "sack_freq", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_sack_freq, 0,
112                 "number of received packets that trigger the sending of a SACK"},
113         { "max_burst", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<10, set_max_burst, 0,
114                 "maximum burst of packets that can be emitted by an association"},
115         {0, 0, 0, 0, 0, 0, 0}
116 };
117
118
119
120 void* sctp_cfg; /* sctp config handle */
121
122 #endif /* USE_SCTP */
123
124 void init_sctp_options()
125 {
126 #ifdef USE_SCTP
127         sctp_get_os_defaults(&sctp_default_cfg);
128 #if 0
129         sctp_default_cfg.so_rcvbuf=0; /* do nothing, use the kernel default */
130         sctp_default_cfg.so_sndbuf=0; /* do nothing, use the kernel default */
131 #endif
132         sctp_default_cfg.autoclose=DEFAULT_SCTP_AUTOCLOSE; /* in seconds */
133         sctp_default_cfg.send_ttl=DEFAULT_SCTP_SEND_TTL;   /* in milliseconds */
134         sctp_default_cfg.send_retries=DEFAULT_SCTP_SEND_RETRIES;
135         sctp_default_cfg.max_assocs=-1; /* as much as possible by default */
136 #ifdef SCTP_CONN_REUSE
137         sctp_default_cfg.assoc_tracking=1; /* on by default */
138         sctp_default_cfg.assoc_reuse=1; /* on by default */
139 #else
140         sctp_default_cfg.assoc_tracking=0;
141         sctp_default_cfg.assoc_reuse=0;
142 #endif /* SCTP_CONN_REUSE */
143 #endif
144 }
145
146
147
148 #define W_OPT_NSCTP(option) \
149         if (sctp_default_cfg.option){\
150                 WARN("sctp_options: " #option \
151                         " cannot be enabled (sctp support not compiled-in)\n"); \
152                         sctp_default_cfg.option=0; \
153         }
154
155
156
157 void sctp_options_check()
158 {
159 #ifndef USE_SCTP
160         W_OPT_NSCTP(autoclose);
161         W_OPT_NSCTP(send_ttl);
162         W_OPT_NSCTP(send_retries);
163         W_OPT_NSCTP(assoc_tracking);
164         W_OPT_NSCTP(assoc_reuse);
165         W_OPT_NSCTP(max_assocs);
166 #else /* USE_SCTP */
167         if (sctp_default_cfg.send_retries>MAX_SCTP_SEND_RETRIES) {
168                 WARN("sctp: sctp_send_retries too high (%d), setting it to %d\n",
169                                 sctp_default_cfg.send_retries, MAX_SCTP_SEND_RETRIES);
170                 sctp_default_cfg.send_retries=MAX_SCTP_SEND_RETRIES;
171         }
172 #ifndef CONN_REUSE
173         if (sctp_default_cfg.assoc_tracking || sctp_default_cfg.assoc_reuse){
174                 WARN("sctp_options: assoc_tracking and assoc_reuse support cannnot"
175                                 " be enabled (CONN_REUSE support not compiled-in)\n");
176                 sctp_default_cfg.assoc_tracking=0;
177                 sctp_default_cfg.assoc_reuse=0;
178         }
179 #else /* CONN_REUSE */
180         if (sctp_default_cfg.assoc_reuse && sctp_default_cfg.assoc_tracking==0){
181                 sctp_default_cfg.assoc_tracking=1;
182         }
183 #endif /* CONN_REUSE */
184 #endif /* USE_SCTP */
185 }
186
187
188
189 void sctp_options_get(struct cfg_group_sctp *s)
190 {
191 #ifdef USE_SCTP
192         *s=*(struct cfg_group_sctp*)sctp_cfg;
193 #else
194         memset(s, 0, sizeof(*s));
195 #endif /* USE_SCTP */
196 }
197
198
199
200 #ifdef USE_SCTP
201 /** register sctp config into the configuration framework.
202  * @return 0 on success, -1 on error */
203 int sctp_register_cfg()
204 {
205         if (cfg_declare("sctp", sctp_cfg_def, &sctp_default_cfg, cfg_sizeof(sctp),
206                                 &sctp_cfg))
207                 return -1;
208         if (sctp_cfg==0){
209                 BUG("null sctp cfg");
210                 return -1;
211         }
212         return 0;
213 }
214
215
216
217 #define SCTP_SET_SOCKOPT_DECLS \
218         int err; \
219         struct socket_info* si
220
221 #define SCTP_SET_SOCKOPT_BODY(lev, opt_name, val, err_prefix) \
222         err=0; \
223         for (si=sctp_listen; si; si=si->next){ \
224                 err+=(sctp_setsockopt(si->socket, (lev), (opt_name), (void*)(&(val)), \
225                                                         sizeof((val)), (err_prefix))<0); \
226         } \
227         return -(err!=0)
228
229
230
231 static int set_autoclose(void* cfg_h, str* gname, str* name, void** val)
232 {
233 #ifdef SCTP_AUTOCLOSE
234         int optval;
235         SCTP_SET_SOCKOPT_DECLS;
236         
237         optval=(int)(long)(*val);
238         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_AUTOCLOSE, optval,
239                                                         "cfg: setting SCTP_AUTOCLOSE");
240 #else
241         ERR("no SCTP_AUTOCLOSE support, please upgrade your sctp library\n");
242         return -1;
243 #endif /* SCTP_AUTOCLOSE */
244 }
245
246
247
248 static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val)
249 {
250         int optval;
251         
252         optval=(int)(long)(*val);
253 #ifndef SCTP_CONN_REUSE
254         if (optval!=0){
255                 ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
256                 return -1;
257         }
258 #else /* SCTP_CONN_REUSE */
259         if (optval==0){
260                 /* turn tracking off */
261                 /* check if assoc_reuse is off */
262                 if (cfg_get(sctp, cfg_h, assoc_reuse)!=0){
263                         ERR("cannot turn sctp assoc_tracking off while assoc_reuse is"
264                                         " still on, please turn assoc_reuse off first\n");
265                         return -1;
266                 }
267                 sctp_con_tracking_flush();
268         }else if (optval==1 && cfg_get(sctp, cfg_h, assoc_reuse)==0){
269                 /* turning from off to on, make sure we flush the tracked list
270                    again, just incase the off flush was racing with a new connection*/
271                 sctp_con_tracking_flush();
272         }
273 #endif /* SCTP_CONN_REUSE */
274         return 0;
275 }
276
277
278
279 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val)
280 {
281         int optval;
282         
283         optval=(int)(long)(*val);
284 #ifndef SCTP_CONN_REUSE
285         if (optval!=0){
286                 ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
287                 return -1;
288         }
289 #else /* SCTP_CONN_REUSE */
290         if (optval==1 && cfg_get(sctp, cfg_h, assoc_tracking)==0){
291                 /* conn reuse on, but assoc_tracking off => not possible */
292                 ERR("cannot turn sctp assoc_reuse on while assoc_tracking is"
293                                         " off, please turn assoc_tracking on first\n");
294                 return -1;
295         }
296 #endif /* SCTP_CONN_REUSE */
297         return 0;
298 }
299
300
301
302 static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val)
303 {
304 #ifdef SCTP_RTOINFO
305         struct sctp_rtoinfo rto;
306         SCTP_SET_SOCKOPT_DECLS;
307         
308         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
309                 *val=(void*)(long)cfg_get(sctp, cfg_h, srto_initial);
310                 return 0;
311         }
312         memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
313         rto.srto_assoc_id=0; /* all */
314         rto.srto_initial=(int)(long)(*val);
315         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
316                                                         "cfg: setting SCTP_RTOINFO");
317 #else
318         ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
319         return -1;
320 #endif /* SCTP_RTOINFO */
321 }
322
323
324
325 static int set_srto_max(void* cfg_h, str* gname, str* name, void** val)
326 {
327 #ifdef SCTP_RTOINFO
328         struct sctp_rtoinfo rto;
329         SCTP_SET_SOCKOPT_DECLS;
330         
331         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
332                 *val=(void*)(long)cfg_get(sctp, cfg_h, srto_max);
333                 return 0;
334         }
335         memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
336         rto.srto_assoc_id=0; /* all */
337         rto.srto_max=(int)(long)(*val);
338         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
339                                                         "cfg: setting SCTP_RTOINFO");
340 #else
341         ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
342         return -1;
343 #endif /* SCTP_RTOINFO */
344 }
345
346
347
348 static int set_srto_min(void* cfg_h, str* gname, str* name, void** val)
349 {
350 #ifdef SCTP_RTOINFO
351         struct sctp_rtoinfo rto;
352         SCTP_SET_SOCKOPT_DECLS;
353         
354         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
355                 *val=(void*)(long)cfg_get(sctp, cfg_h, srto_min);
356                 return 0;
357         }
358         memset(&rto, 0, sizeof(rto)); /* zero everything we don't care about */
359         rto.srto_assoc_id=0; /* all */
360         rto.srto_min=(int)(long)(*val);
361         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_RTOINFO, rto,
362                                                         "cfg: setting SCTP_RTOINFO");
363 #else
364         ERR("no SCTP_RTOINFO support, please upgrade your sctp library\n");
365         return -1;
366 #endif /* SCTP_RTOINFO */
367 }
368
369
370
371 static int set_asocmaxrxt(void* cfg_h, str* gname, str* name, void** val)
372 {
373 #ifdef SCTP_ASSOCINFO
374         struct sctp_assocparams ap;
375         SCTP_SET_SOCKOPT_DECLS;
376         
377         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
378                 *val=(void*)(long)cfg_get(sctp, cfg_h, asocmaxrxt);
379                 return 0;
380         }
381         memset(&ap, 0, sizeof(ap)); /* zero everything we don't care about */
382         ap.sasoc_assoc_id=0; /* all */
383         ap.sasoc_asocmaxrxt=(int)(long)(*val);
384         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_ASSOCINFO, ap,
385                                                         "cfg: setting SCTP_ASSOCINFO");
386 #else
387         ERR("no SCTP_ASSOCINFO support, please upgrade your sctp library\n");
388         return -1;
389 #endif /* SCTP_ASSOCINFO */
390 }
391
392
393
394 static int set_sinit_max_init_timeo(void* cfg_h, str* gname, str* name,
395                                                                         void** val)
396 {
397 #ifdef SCTP_INITMSG
398         struct sctp_initmsg im;
399         SCTP_SET_SOCKOPT_DECLS;
400         
401         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
402                 *val=(void*)(long)cfg_get(sctp, cfg_h, init_max_timeo);
403                 return 0;
404         }
405         memset(&im, 0, sizeof(im)); /* zero everything we don't care about */
406         im.sinit_max_init_timeo=(int)(long)(*val);
407         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_INITMSG, im,
408                                                         "cfg: setting SCTP_INITMSG");
409 #else
410         ERR("no SCTP_INITMSG support, please upgrade your sctp library\n");
411         return -1;
412 #endif /* SCTP_INITMSG */
413 }
414
415
416
417 static int set_sinit_max_attempts(void* cfg_h, str* gname, str* name,
418                                                                         void** val)
419 {
420 #ifdef SCTP_INITMSG
421         struct sctp_initmsg im;
422         SCTP_SET_SOCKOPT_DECLS;
423         
424         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
425                 *val=(void*)(long)cfg_get(sctp, cfg_h, init_max_attempts);
426                 return 0;
427         }
428         memset(&im, 0, sizeof(im)); /* zero everything we don't care about */
429         im.sinit_max_attempts=(int)(long)(*val);
430         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_INITMSG, im,
431                                                         "cfg: setting SCTP_INITMSG");
432 #else
433         ERR("no SCTP_INITMSG support, please upgrade your sctp library\n");
434         return -1;
435 #endif /* SCTP_INITMSG */
436 }
437
438
439
440 static int set_hbinterval(void* cfg_h, str* gname, str* name,
441                                                                         void** val)
442 {
443 #ifdef SCTP_PEER_ADDR_PARAMS
444         struct sctp_paddrparams pp;
445         SCTP_SET_SOCKOPT_DECLS;
446         
447         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
448                 *val=(void*)(long)cfg_get(sctp, cfg_h, hbinterval);
449                 return 0;
450         }
451         memset(&pp, 0, sizeof(pp)); /* zero everything we don't care about */
452         if ((int)(long)(*val)!=-1){
453                 pp.spp_hbinterval=(int)(long)(*val);
454                 pp.spp_flags=SPP_HB_ENABLE;
455         }else{
456                 pp.spp_flags=SPP_HB_DISABLE;
457         }
458         err=0;
459         for (si=sctp_listen; si; si=si->next){
460                 /* set the AF, needed on older linux kernels even for INADDR_ANY */
461                 pp.spp_address.ss_family=si->address.af;
462                 err+=(sctp_setsockopt(si->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
463                                                                 (void*)(&pp), sizeof(pp),
464                                                                 "cfg: setting SCTP_PEER_ADDR_PARAMS")<0);
465         }
466         return -(err!=0);
467 #else
468         ERR("no SCTP_PEER_ADDR_PARAMS support, please upgrade your"
469                         " sctp library\n");
470         return -1;
471 #endif /* SCTP_PEER_ADDR_PARAMS */
472 }
473
474
475
476 static int set_pathmaxrxt(void* cfg_h, str* gname, str* name,
477                                                                         void** val)
478 {
479 #ifdef SCTP_PEER_ADDR_PARAMS
480         struct sctp_paddrparams pp;
481         SCTP_SET_SOCKOPT_DECLS;
482         
483         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
484                 *val=(void*)(long)cfg_get(sctp, cfg_h, pathmaxrxt);
485                 return 0;
486         }
487         memset(&pp, 0, sizeof(pp)); /* zero everything we don't care about */
488         pp.spp_pathmaxrxt=(int)(long)(*val);
489         err=0;
490         for (si=sctp_listen; si; si=si->next){
491                 /* set the AF, needed on older linux kernels even for INADDR_ANY */
492                 pp.spp_address.ss_family=si->address.af;
493                 err+=(sctp_setsockopt(si->socket, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
494                                                                 (void*)(&pp), sizeof(pp),
495                                                                 "cfg: setting SCTP_PEER_ADDR_PARAMS")<0);
496         }
497         return -(err!=0);
498 #else
499         ERR("no SCTP_PEER_ADDR_PARAMS support, please upgrade your"
500                         " sctp library\n");
501         return -1;
502 #endif /* SCTP_PEER_ADDR_PARAMS */
503 }
504
505
506
507 static int set_sack_delay(void* cfg_h, str* gname, str* name, void** val)
508 {
509 #if defined SCTP_DELAYED_SACK || defined SCTP_DELAYED_ACK_TIME
510 #ifdef SCTP_DELAYED_SACK
511         struct sctp_sack_info sa;
512 #else /* old lib */
513         struct sctp_assoc_value sa;
514 #endif /* SCTP_DELAYED_SACK */
515         SCTP_SET_SOCKOPT_DECLS;
516         
517         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
518                 *val=(void*)(long)cfg_get(sctp, cfg_h, sack_delay);
519                 return 0;
520         }
521         memset(&sa, 0, sizeof(sa)); /* zero everything we don't care about */
522 #ifdef SCTP_DELAYED_SACK
523         sa.sack_delay=(int)(long)(*val);
524         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_SACK, sa,
525                                                         "cfg: setting SCTP_DELAYED_SACK");
526 #else /* old sctp lib version which uses SCTP_DELAYED_ACK_TIME */
527         sa.assoc_value=(int)(long)(*val);
528         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_ACK_TIME, sa,
529                                                         "cfg: setting SCTP_DELAYED_ACK_TIME");
530 #endif /* SCTP_DELAYED_SACK */
531 #else
532         ERR("no SCTP_DELAYED_SACK support, please upgrade your sctp library\n");
533         return -1;
534 #endif /* SCTP_DELAYED_SACK | SCTP_DELAYED_ACK_TIME */
535 }
536
537
538
539 static int set_sack_freq(void* cfg_h, str* gname, str* name, void** val)
540 {
541 #ifdef SCTP_DELAYED_SACK
542         struct sctp_sack_info sa;
543         SCTP_SET_SOCKOPT_DECLS;
544         
545         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
546                 *val=(void*)(long)cfg_get(sctp, cfg_h, sack_freq);
547                 return 0;
548         }
549         memset(&sa, 0, sizeof(sa)); /* zero everything we don't care about */
550         sa.sack_freq=(int)(long)(*val);
551         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_DELAYED_SACK, sa,
552                                                         "cfg: setting SCTP_DELAYED_SACK");
553 #else
554         ERR("no SCTP_DELAYED_SACK support, please upgrade your sctp library\n");
555         return -1;
556 #endif /* SCTP_DELAYED_SACK */
557 }
558
559
560
561 static int set_max_burst(void* cfg_h, str* gname, str* name, void** val)
562 {
563 #ifdef SCTP_MAX_BURST
564         struct sctp_assoc_value av;
565         SCTP_SET_SOCKOPT_DECLS;
566         
567         if ((int)(long)(*val)==0){ /* do nothing for 0, keep the old value */
568                 *val=(void*)(long)cfg_get(sctp, cfg_h, max_burst);
569                 return 0;
570         }
571         memset(&av, 0, sizeof(av)); /* zero everything we don't care about */
572         av.assoc_value=(int)(long)(*val);
573         SCTP_SET_SOCKOPT_BODY(IPPROTO_SCTP, SCTP_MAX_BURST, av,
574                                                         "cfg: setting SCTP_MAX_BURST");
575 #else
576         ERR("no SCTP_MAX_BURST support, please upgrade your sctp library\n");
577         return -1;
578 #endif /* SCTP_MAX_BURST */
579 }
580
581 #endif /* USE_SCTP */