1 /*********************************************************************************************************
2 * Software License Agreement (BSD License)                                                               *
3 * Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
4 *													 *
5 * Copyright (c) 2020, WIDE Project and NICT								 *
6 * All rights reserved.											 *
7 * 													 *
8 * Redistribution and use of this software in source and binary forms, with or without modification, are  *
9 * permitted provided that the following conditions are met:						 *
10 * 													 *
11 * * Redistributions of source code must retain the above 						 *
12 *   copyright notice, this list of conditions and the 							 *
13 *   following disclaimer.										 *
14 *    													 *
15 * * Redistributions in binary form must reproduce the above 						 *
16 *   copyright notice, this list of conditions and the 							 *
17 *   following disclaimer in the documentation and/or other						 *
18 *   materials provided with the distribution.								 *
19 * 													 *
20 * * Neither the name of the WIDE Project or NICT nor the 						 *
21 *   names of its contributors may be used to endorse or 						 *
22 *   promote products derived from this software without 						 *
23 *   specific prior written permission of WIDE Project and 						 *
24 *   NICT.												 *
25 * 													 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
34 *********************************************************************************************************/
35 
36 #include "fdcore-internal.h"
37 #include "cnxctx.h"
38 
39 #include <netinet/sctp.h>
40 #include <sys/uio.h>
41 
42 /* Size of buffer to receive ancilliary data. May need to be enlarged if more sockopt are set... */
43 #ifndef CMSG_BUF_LEN
44 #define CMSG_BUF_LEN	1024
45 #endif /* CMSG_BUF_LEN */
46 
47 /* Use old draft-ietf-tsvwg-sctpsocket-17 API ? If not defined, RFC6458 API will be used */
48 /* #define OLD_SCTP_SOCKET_API */
49 
50 /* Automatically fallback to old API if some of the new symbols are not defined */
51 #if (!defined(SCTP_CONNECTX_4_ARGS) || (!defined(SCTP_RECVRCVINFO)) || (!defined(SCTP_SNDINFO)) || (!defined(SCTP_SEND_FAILED_EVENT)))
52 # define OLD_SCTP_SOCKET_API
53 #endif
54 
55 
56 /* Temper with the retransmission timers to try and improve disconnection detection response? Undef this to keep the defaults of SCTP stack */
57 #ifndef USE_DEFAULT_SCTP_RTX_PARAMS	/* make this a configuration option if useful */
58 #define ADJUST_RTX_PARAMS
59 #endif /* USE_DEFAULT_SCTP_RTX_PARAMS */
60 
61 
DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_array,sSA * saddrs,int saddrs_count)62 DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_array, sSA * saddrs, int saddrs_count)
63 {
64 	union {
65 		sSA	*sa;
66 		uint8_t *buf;
67 	} ptr;
68 	int i;
69 	int salen;
70 
71 	FD_DUMP_HANDLE_OFFSET();
72 
73 	ptr.sa = saddrs;
74 	for (i = 0; i < saddrs_count; i++) {
75 		salen = sSAlen(ptr.sa);
76 		if (salen == 0) {
77 			LOG_E("fd_sa_dump_array: Unknown sockaddr family");
78 			break;
79 		}
80 		if (i > 0) {
81 			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " "), return NULL);
82 		}
83 		CHECK_MALLOC_DO( fd_sa_dump( FD_DUMP_STD_PARAMS, ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV), return NULL);
84 		ptr.buf += salen;
85 	}
86 	return *buf;
87 }
88 
89 /* Pre-binding socket options -- # streams read in config */
fd_setsockopt_prebind(int sk)90 static int fd_setsockopt_prebind(int sk)
91 {
92 	socklen_t sz;
93 
94 	TRACE_ENTRY( "%d", sk);
95 
96 	CHECK_PARAMS( sk > 0 );
97 
98 	{
99 		int reuse = 1;
100 		CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))  );
101 	}
102 
103 #ifdef ADJUST_RTX_PARAMS
104 	/* Set the retransmit parameters */
105 	#ifdef SCTP_RTOINFO
106 	{
107 		struct sctp_rtoinfo rtoinfo;
108 		memset(&rtoinfo, 0, sizeof(rtoinfo));
109 
110 		if (TRACE_BOOL(ANNOYING)) {
111 			sz = sizeof(rtoinfo);
112 			/* Read socket defaults */
113 			CHECK_SYS(  sctp_opt_info(sk, 0, SCTP_RTOINFO, &rtoinfo, &sz)  );
114 			if (sz != sizeof(rtoinfo))
115 			{
116 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo));
117 				return ENOTSUP;
118 			}
119 			fd_log_debug( "Def SCTP_RTOINFO : srto_initial : %u", rtoinfo.srto_initial);
120 			fd_log_debug( "                   srto_min     : %u", rtoinfo.srto_min);
121 			fd_log_debug( "                   srto_max     : %u", rtoinfo.srto_max);
122 		}
123 
124 		/* rtoinfo.srto_initial: Estimate of the RTT before it can be measured; keep the default value */
125 		rtoinfo.srto_max = 5000; /* Maximum retransmit timer (in ms), we want fast retransmission time. */
126 		rtoinfo.srto_min = 1000; /* Value under which the RTO does not descend, we set this value to not conflict with srto_max */
127 
128 		/* Set the option to the socket */
129 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo))  );
130 
131 		if (TRACE_BOOL(ANNOYING)) {
132 			/* Check new values */
133 			CHECK_SYS(  sctp_opt_info(sk, 0, SCTP_RTOINFO, &rtoinfo, &sz)  );
134 			fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u", rtoinfo.srto_initial);
135 			fd_log_debug( "                   srto_max     : %u", rtoinfo.srto_max);
136 			fd_log_debug( "                   srto_min     : %u", rtoinfo.srto_min);
137 		}
138 	}
139 	#else /* SCTP_RTOINFO */
140 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_RTOINFO");
141 	#endif /* SCTP_RTOINFO */
142 
143 	/* Set the association parameters: max number of retransmits, ... */
144 	#ifdef SCTP_ASSOCINFO
145 	{
146 		struct sctp_assocparams assoc;
147 		memset(&assoc, 0, sizeof(assoc));
148 
149 		if (TRACE_BOOL(ANNOYING)) {
150 			sz = sizeof(assoc);
151 			/* Read socket defaults */
152 			CHECK_SYS(  sctp_opt_info(sk, 0, SCTP_ASSOCINFO, &assoc, &sz)  );
153 			if (sz != sizeof(assoc))
154 			{
155 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc));
156 				return ENOTSUP;
157 			}
158 			fd_log_debug( "Def SCTP_ASSOCINFO : sasoc_asocmaxrxt               : %hu", assoc.sasoc_asocmaxrxt);
159 			fd_log_debug( "                     sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
160 			fd_log_debug( "                     sasoc_peer_rwnd                : %u" , assoc.sasoc_peer_rwnd);
161 			fd_log_debug( "                     sasoc_local_rwnd               : %u" , assoc.sasoc_local_rwnd);
162 			fd_log_debug( "                     sasoc_cookie_life              : %u" , assoc.sasoc_cookie_life);
163 		}
164 
165 		assoc.sasoc_asocmaxrxt = 4;	/* Maximum number of retransmission attempts: we want fast detection of errors */
166 						/* Note that this must remain less than the sum of retransmission parameters of the different paths. */
167 
168 		/* Set the option to the socket */
169 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc))  );
170 
171 		if (TRACE_BOOL(ANNOYING)) {
172 			/* Check new values */
173 			CHECK_SYS(  sctp_opt_info(sk, 0, SCTP_ASSOCINFO, &assoc, &sz)  );
174 			fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt               : %hu", assoc.sasoc_asocmaxrxt);
175 			fd_log_debug( "                     sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
176 			fd_log_debug( "                     sasoc_peer_rwnd                : %u" , assoc.sasoc_peer_rwnd);
177 			fd_log_debug( "                     sasoc_local_rwnd               : %u" , assoc.sasoc_local_rwnd);
178 			fd_log_debug( "                     sasoc_cookie_life              : %u" , assoc.sasoc_cookie_life);
179 		}
180 	}
181 	#else /* SCTP_ASSOCINFO */
182 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_ASSOCINFO");
183 	#endif /* SCTP_ASSOCINFO */
184 #endif /* ADJUST_RTX_PARAMS */
185 
186 	/* Set the INIT parameters, such as number of streams */
187 	#ifdef SCTP_INITMSG
188 	{
189 		struct sctp_initmsg init;
190 		memset(&init, 0, sizeof(init));
191 
192 		if (TRACE_BOOL(ANNOYING)) {
193 			sz = sizeof(init);
194 
195 			/* Read socket defaults */
196 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
197 			if (sz != sizeof(init))
198 			{
199 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init));
200 				return ENOTSUP;
201 			}
202 			fd_log_debug( "Def SCTP_INITMSG : sinit_num_ostreams   : %hu", init.sinit_num_ostreams);
203 			fd_log_debug( "                   sinit_max_instreams  : %hu", init.sinit_max_instreams);
204 			fd_log_debug( "                   sinit_max_attempts   : %hu", init.sinit_max_attempts);
205 			fd_log_debug( "                   sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
206 		}
207 
208 		/* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters, but we don't care (best effort) */
209 		init.sinit_num_ostreams	  = fd_g_config->cnf_sctp_str;	/* desired number of outgoing streams */
210 		init.sinit_max_init_timeo = CNX_TIMEOUT * 1000;
211 
212 		/* Set the option to the socket */
213 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init))  );
214 
215 		if (TRACE_BOOL(ANNOYING)) {
216 			/* Check new values */
217 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
218 			fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams   : %hu", init.sinit_num_ostreams);
219 			fd_log_debug( "                   sinit_max_instreams  : %hu", init.sinit_max_instreams);
220 			fd_log_debug( "                   sinit_max_attempts   : %hu", init.sinit_max_attempts);
221 			fd_log_debug( "                   sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
222 		}
223 	}
224 	#else /* SCTP_INITMSG */
225 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_INITMSG");
226 	#endif /* SCTP_INITMSG */
227 
228 	/* The SO_LINGER option will be reset if we want to perform SCTP ABORT */
229 	#ifdef SO_LINGER
230 	{
231 		struct linger linger;
232 		memset(&linger, 0, sizeof(linger));
233 
234 		if (TRACE_BOOL(ANNOYING)) {
235 			sz = sizeof(linger);
236 			/* Read socket defaults */
237 			CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
238 			if (sz != sizeof(linger))
239 			{
240 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger));
241 				return ENOTSUP;
242 			}
243 			fd_log_debug( "Def SO_LINGER : l_onoff  : %d", linger.l_onoff);
244 			fd_log_debug( " 	       l_linger : %d", linger.l_linger);
245 		}
246 
247 		linger.l_onoff	= 0;	/* Do not activate the linger */
248 		linger.l_linger = 0;	/* Ignored, but it would mean : Return immediately when closing (=> abort) (graceful shutdown in background) */
249 
250 		/* Set the option */
251 		CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))  );
252 
253 		if (TRACE_BOOL(ANNOYING)) {
254 			/* Check new values */
255 			CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
256 			fd_log_debug( "New SO_LINGER : l_onoff  : %d", linger.l_onoff);
257 			fd_log_debug( "		  l_linger : %d", linger.l_linger);
258 		}
259 	}
260 	#else /* SO_LINGER */
261 	TRACE_DEBUG(ANNOYING, "Skipping SO_LINGER");
262 	#endif /* SO_LINGER */
263 
264 	/* Set the NODELAY option (Nagle-like algorithm) */
265 	#ifdef SCTP_NODELAY
266 	{
267 		int nodelay;
268 
269 		if (TRACE_BOOL(ANNOYING)) {
270 			sz = sizeof(nodelay);
271 			/* Read socket defaults */
272 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
273 			if (sz != sizeof(nodelay))
274 			{
275 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay));
276 				return ENOTSUP;
277 			}
278 			fd_log_debug( "Def SCTP_NODELAY value : %s", nodelay ? "true" : "false");
279 		}
280 
281 		nodelay = 1;	/* We turn ON to disable the Nagle algorithm, so that packets are sent ASAP. */
282 
283 		/* Set the option to the socket */
284 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay))  );
285 
286 		if (TRACE_BOOL(ANNOYING)) {
287 			/* Check new values */
288 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
289 			fd_log_debug( "New SCTP_NODELAY value : %s", nodelay ? "true" : "false");
290 		}
291 	}
292 	#else /* SCTP_NODELAY */
293 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_NODELAY");
294 	#endif /* SCTP_NODELAY */
295 
296 	/*
297 	   SO_RCVBUF			size of receiver window
298 	   SO_SNDBUF			size of pending data to send
299 	   SCTP_AUTOCLOSE		for one-to-many only
300 	   SCTP_PRIMARY_ADDR		use this address as primary locally
301 	   SCTP_ADAPTATION_LAYER	set adaptation layer indication, we don't use this
302 	*/
303 
304 	/* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */
305 	#ifdef SCTP_DISABLE_FRAGMENTS
306 	{
307 		int nofrag;
308 
309 		if (TRACE_BOOL(ANNOYING)) {
310 			sz = sizeof(nofrag);
311 			/* Read socket defaults */
312 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
313 			if (sz != sizeof(nofrag))
314 			{
315 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag));
316 				return ENOTSUP;
317 			}
318 			fd_log_debug( "Def SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
319 		}
320 
321 		nofrag = 0;	/* We turn ON the fragmentation, since Diameter messages & TLS messages can be quite large. */
322 
323 		/* Set the option to the socket */
324 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag))  );
325 
326 		if (TRACE_BOOL(ANNOYING)) {
327 			/* Check new values */
328 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
329 			fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
330 		}
331 	}
332 	#else /* SCTP_DISABLE_FRAGMENTS */
333 	# error "TLS requires support of SCTP_DISABLE_FRAGMENTS"
334 	#endif /* SCTP_DISABLE_FRAGMENTS */
335 
336 	/* SCTP_PEER_ADDR_PARAMS	control heartbeat per peer address. We set it as a default for all addresses in the association; not sure if it works ... */
337 	#ifdef SCTP_PEER_ADDR_PARAMS
338 	{
339 		struct sctp_paddrparams parms;
340 		memset(&parms, 0, sizeof(parms));
341 
342 		/* Some kernel versions need this to be set */
343 		parms.spp_address.ss_family = AF_INET;
344 
345 		if (TRACE_BOOL(ANNOYING)) {
346 			sz = sizeof(parms);
347 
348 			/* Read socket defaults */
349 			CHECK_SYS(  sctp_opt_info(sk, 0, SCTP_PEER_ADDR_PARAMS, &parms, &sz)  );
350 			if (sz != sizeof(parms))
351 			{
352 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(parms));
353 				return ENOTSUP;
354 			}
355 			fd_log_debug( "Def SCTP_PEER_ADDR_PARAMS : spp_hbinterval    : %u",  parms.spp_hbinterval);
356 			fd_log_debug( "                            spp_pathmaxrxt    : %hu", parms.spp_pathmaxrxt);
357 			fd_log_debug( "                            spp_pathmtu       : %u",  parms.spp_pathmtu);
358 			fd_log_debug( "                            spp_flags         : %x",  parms.spp_flags);
359 			// fd_log_debug( "                            spp_ipv6_flowlabel: %u",  parms.spp_ipv6_flowlabel);
360 			// fd_log_debug( "                            spp_ipv4_tos      : %hhu",parms.spp_ipv4_tos);
361 		}
362 
363 		parms.spp_flags = SPP_HB_ENABLE;	/* Enable heartbeat for the association */
364 		#ifdef SPP_PMTUD_ENABLE
365 		parms.spp_flags |= SPP_PMTUD_ENABLE;	/* also enable path MTU discovery mechanism */
366 		#endif /* SPP_PMTUD_ENABLE */
367 
368 #ifdef ADJUST_RTX_PARAMS
369 		parms.spp_hbinterval = 6000;		/* Send an heartbeat every 6 seconds to quickly start retransmissions */
370 		/* parms.spp_pathmaxrxt : max nbr of restransmissions on this address. There is a relationship with sasoc_asocmaxrxt, so we leave the default here */
371 #endif /* ADJUST_RTX_PARAMS */
372 
373 		/* Set the option to the socket */
374 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, sizeof(parms)) );
375 
376 		if (TRACE_BOOL(ANNOYING)) {
377 			/* Check new values */
378 			CHECK_SYS(  sctp_opt_info(sk, 0, SCTP_PEER_ADDR_PARAMS, &parms, &sz)  );
379 			fd_log_debug( "New SCTP_PEER_ADDR_PARAMS : spp_hbinterval    : %u",  parms.spp_hbinterval);
380 			fd_log_debug( "                            spp_pathmaxrxt    : %hu", parms.spp_pathmaxrxt);
381 			fd_log_debug( "                            spp_pathmtu       : %u",  parms.spp_pathmtu);
382 			fd_log_debug( "                            spp_flags         : %x",  parms.spp_flags);
383 			// fd_log_debug( "                            spp_ipv6_flowlabel: %u",  parms.spp_ipv6_flowlabel);
384 			// fd_log_debug( "                            spp_ipv4_tos      : %hhu",parms.spp_ipv4_tos);
385 		}
386 	}
387 	#else /* SCTP_PEER_ADDR_PARAMS */
388 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_PEER_ADDR_PARAMS");
389 	#endif /* SCTP_PEER_ADDR_PARAMS */
390 
391 	/*
392 	   SCTP_DEFAULT_SEND_PARAM - DEPRECATED // parameters for the sendto() call, we don't use it.
393 	*/
394 
395 	/* Subscribe to some notifications */
396 #ifdef OLD_SCTP_SOCKET_API
397 	#ifdef SCTP_EVENTS /* DEPRECATED */
398 	{
399 		struct sctp_event_subscribe event;
400 
401 		memset(&event, 0, sizeof(event));
402 		event.sctp_data_io_event	= 1;	/* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */
403 		event.sctp_association_event	= 0;	/* new or closed associations (mostly for one-to-many style sockets) */
404 		event.sctp_address_event	= 1;	/* address changes */
405 		event.sctp_send_failure_event	= 1;	/* delivery failures */
406 		event.sctp_peer_error_event	= 1;	/* remote peer sends an error */
407 		event.sctp_shutdown_event	= 1;	/* peer has sent a SHUTDOWN */
408 		event.sctp_partial_delivery_event = 1;	/* a partial delivery is aborted, probably indicating the connection is being shutdown */
409 		// event.sctp_adaptation_layer_event = 0;	/* adaptation layer notifications */
410 		// event.sctp_authentication_event = 0;	/* when new key is made active */
411 
412 		/* Set the option to the socket */
413 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) );
414 
415 		if (TRACE_BOOL(ANNOYING)) {
416 			sz = sizeof(event);
417 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) );
418 			if (sz != sizeof(event))
419 			{
420 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event));
421 				return ENOTSUP;
422 			}
423 
424 			fd_log_debug( "SCTP_EVENTS : sctp_data_io_event          : %hhu", event.sctp_data_io_event);
425 			fd_log_debug( "       	     sctp_association_event      : %hhu", event.sctp_association_event);
426 			fd_log_debug( "       	     sctp_address_event	         : %hhu", event.sctp_address_event);
427 			fd_log_debug( "       	     sctp_send_failure_event     : %hhu", event.sctp_send_failure_event);
428 			fd_log_debug( "       	     sctp_peer_error_event       : %hhu", event.sctp_peer_error_event);
429 			fd_log_debug( "       	     sctp_shutdown_event	 : %hhu", event.sctp_shutdown_event);
430 			fd_log_debug( "       	     sctp_partial_delivery_event : %hhu", event.sctp_partial_delivery_event);
431 			// fd_log_debug( "       	     sctp_adaptation_layer_event : %hhu", event.sctp_adaptation_layer_event);
432 			// fd_log_debug( "             sctp_authentication_event    : %hhu", event.sctp_authentication_event);
433 		}
434 	}
435 	#else /* SCTP_EVENTS */
436 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_EVENTS");
437 	#endif /* SCTP_EVENTS */
438 #endif /*  OLD_SCTP_SOCKET_API */
439 
440 	/* Set the v4 mapped addresses option */
441 	#ifdef SCTP_I_WANT_MAPPED_V4_ADDR
442 	if (!fd_g_config->cnf_flags.no_ip6) {
443 		int v4mapped;
444 
445 		if (TRACE_BOOL(ANNOYING)) {
446 			sz = sizeof(v4mapped);
447 			/* Read socket defaults */
448 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
449 			if (sz != sizeof(v4mapped))
450 			{
451 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped));
452 				return ENOTSUP;
453 			}
454 			fd_log_debug( "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
455 		}
456 
457 		#ifndef SCTP_USE_MAPPED_ADDRESSES
458 		v4mapped = 0;	/* We don't want v4 mapped addresses */
459 		#else /* SCTP_USE_MAPPED_ADDRESSES */
460 		v4mapped = 1;	/* but we may have to, otherwise the bind fails in some environments */
461 		#endif /* SCTP_USE_MAPPED_ADDRESSES */
462 
463 		/* Set the option to the socket */
464 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped))  );
465 
466 		if (TRACE_BOOL(ANNOYING)) {
467 			/* Check new values */
468 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
469 			fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
470 		}
471 	} else {
472 		TRACE_DEBUG(ANNOYING, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR, since IPv6 disabled.");
473 	}
474 	#else /* SCTP_I_WANT_MAPPED_V4_ADDR */
475 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
476 	#endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
477 
478 	/*
479 	   SCTP_MAXSEG			max size of fragmented segments -- bound to PMTU
480 	   SCTP_HMAC_IDENT		authentication algorithms
481 	   SCTP_AUTH_ACTIVE_KEY		set the active key
482 	   SCTP_DELAYED_SACK		control delayed acks
483 	*/
484 
485 
486 	/* Set the interleaving option */
487 	#ifdef SCTP_FRAGMENT_INTERLEAVE
488 	{
489 		int interleave;
490 
491 		if (TRACE_BOOL(ANNOYING)) {
492 			sz = sizeof(interleave);
493 			/* Read socket defaults */
494 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
495 			if (sz != sizeof(interleave))
496 			{
497 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(interleave));
498 				return ENOTSUP;
499 			}
500 			fd_log_debug( "Def SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
501 		}
502 
503 		#if 0
504 		interleave = 2;	/* Allow partial delivery on several streams at the same time, since we are stream-aware in our security modules */
505 		#else /* 0 */
506 		interleave = 1;	/* hmmm actually, we are not yet capable of handling this, and we don t need it. */
507 		#endif /* 0 */
508 
509 		/* Set the option to the socket */
510 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave))  );
511 
512 		if (TRACE_BOOL(ANNOYING)) {
513 			/* Check new values */
514 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
515 			fd_log_debug( "New SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
516 		}
517 	}
518 	#else /* SCTP_FRAGMENT_INTERLEAVE */
519 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_FRAGMENT_INTERLEAVE");
520 	#endif /* SCTP_FRAGMENT_INTERLEAVE */
521 
522 	/*
523 	   SCTP_PARTIAL_DELIVERY_POINT	control partial delivery size
524 	   SCTP_USE_EXT_RCVINFO	- DEPRECATED	use extended receive info structure (information about the next message if available)
525 	 */
526 	/* SCTP_AUTO_ASCONF is set by the postbind function */
527 	/*
528 	   SCTP_MAX_BURST		number of packets that can be burst emitted
529 	   SCTP_CONTEXT			save a context information along with the association.
530 	 */
531 
532 	/* SCTP_EXPLICIT_EOR: we assume implicit EOR in freeDiameter, so let's ensure this is known by the stack */
533 	#ifdef SCTP_EXPLICIT_EOR
534 	{
535 		int bool;
536 
537 		if (TRACE_BOOL(ANNOYING)) {
538 			sz = sizeof(bool);
539 			/* Read socket defaults */
540 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz)  );
541 			if (sz != sizeof(bool))
542 			{
543 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(bool));
544 				return ENOTSUP;
545 			}
546 			fd_log_debug( "Def SCTP_EXPLICIT_EOR value : %s", bool ? "true" : "false");
547 		}
548 
549 		bool = 0;
550 
551 		/* Set the option to the socket */
552 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, sizeof(bool))  );
553 
554 		if (TRACE_BOOL(ANNOYING)) {
555 			/* Check new values */
556 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz)  );
557 			fd_log_debug( "New SCTP_EXPLICIT_EOR value : %s", bool ? "true" : "false");
558 		}
559 	}
560 	#else /* SCTP_EXPLICIT_EOR */
561 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_EXPLICIT_EOR");
562 	#endif /* SCTP_EXPLICIT_EOR */
563 
564 	/*
565 	   SCTP_REUSE_PORT		share one listening port with several sockets
566 	*/
567 
568 #ifndef OLD_SCTP_SOCKET_API
569 	#ifdef SCTP_EVENT
570 	{
571 		/* Subscribe to the following events */
572 		int events_I_want[] = {
573 		#ifdef SCTP_ASSOC_CHANGE
574 			/* SCTP_ASSOC_CHANGE, */
575 		#endif
576 		#ifdef SCTP_PEER_ADDR_CHANGE
577 			SCTP_PEER_ADDR_CHANGE,
578 		#endif
579 		#ifdef SCTP_REMOTE_ERROR
580 			SCTP_REMOTE_ERROR,
581 		#endif
582 		#ifdef SCTP_SEND_FAILED_EVENT
583 			SCTP_SEND_FAILED_EVENT,
584 		#endif
585 		#ifdef SCTP_SHUTDOWN_EVENT
586 			SCTP_SHUTDOWN_EVENT,
587 		#endif
588 		#ifdef SCTP_ADAPTATION_INDICATION
589 			/* SCTP_ADAPTATION_INDICATION, */
590 		#endif
591 		#ifdef SCTP_PARTIAL_DELIVERY_EVENT
592 			/* SCTP_PARTIAL_DELIVERY_EVENT, */
593 		#endif
594 		#ifdef SCTP_AUTHENTICATION_EVENT
595 			/* SCTP_AUTHENTICATION_EVENT, */
596 		#endif
597 		#ifdef SCTP_SENDER_DRY_EVENT
598 			/* SCTP_SENDER_DRY_EVENT, */
599 		#endif
600 			0
601 		};
602 		int i;
603 
604 		struct sctp_event event;
605 
606 		for (i = 0; i < (sizeof(events_I_want) / sizeof(events_I_want[0]) - 1); i++) {
607 			memset(&event, 0, sizeof(event));
608 			event.se_type = events_I_want[i];
609 			event.se_on = 1;
610 
611 			/* Set the option to the socket */
612 			CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) );
613 		}
614 	}
615 	#else /* SCTP_EVENT */
616 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_EVENT");
617 	#endif /* SCTP_EVENT */
618 
619 
620 	#ifdef SCTP_RECVRCVINFO /* Replaces SCTP_SNDRCV */
621 	{
622 		int bool = 1;
623 
624 		/* Set the option to the socket */
625 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_RECVRCVINFO, &bool, sizeof(bool))  );
626 
627 	}
628 	#else /* SCTP_RECVRCVINFO */
629 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_RECVRCVINFO");
630 	#endif /* SCTP_RECVRCVINFO */
631 
632 
633 #endif /* OLD_SCTP_SOCKET_API */
634 
635 	/*
636 		SCTP_RECVNXTINFO
637 
638 		SCTP_DEFAULT_SNDINFO : send defaults
639 		SCTP_DEFAULT_PRINFO  : default PR-SCTP
640 	*/
641 
642 
643 	/* In case of no_ip4, force the v6only option */
644 	#ifdef IPV6_V6ONLY
645 	if (fd_g_config->cnf_flags.no_ip4) {
646 		int opt = 1;
647 		CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
648 	}
649 	#endif /* IPV6_V6ONLY */
650 
651 	return 0;
652 }
653 
654 
655 /* Post-binding socket options */
fd_setsockopt_postbind(int sk,int bound_to_default)656 static int fd_setsockopt_postbind(int sk, int bound_to_default)
657 {
658 	TRACE_ENTRY( "%d %d", sk, bound_to_default);
659 
660 	CHECK_PARAMS( (sk > 0) );
661 
662 	/* Set the ASCONF option */
663 	#ifdef SCTP_AUTO_ASCONF
664 	if (bound_to_default) {
665 		int asconf;
666 
667 		if (TRACE_BOOL(ANNOYING)) {
668 			socklen_t sz;
669 
670 			sz = sizeof(asconf);
671 			/* Read socket defaults */
672 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
673 			if (sz != sizeof(asconf))
674 			{
675 				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(asconf));
676 				return ENOTSUP;
677 			}
678 			fd_log_debug( "Def SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
679 		}
680 
681 		asconf = 1;	/* allow automatic use of added or removed addresses in the association (for bound-all sockets) */
682 
683 		/* Set the option to the socket */
684 		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf))  );
685 
686 		if (TRACE_BOOL(ANNOYING)) {
687 			socklen_t sz = sizeof(asconf);
688 			/* Check new values */
689 			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
690 			fd_log_debug( "New SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
691 		}
692 	}
693 	#else /* SCTP_AUTO_ASCONF */
694 	TRACE_DEBUG(ANNOYING, "Skipping SCTP_AUTO_ASCONF");
695 	#endif /* SCTP_AUTO_ASCONF */
696 
697 	return 0;
698 }
699 
700 /* Add addresses from a list to an array, with filter on the flags */
add_addresses_from_list_mask(uint8_t ** array,size_t * size,int * addr_count,int target_family,uint16_t port,struct fd_list * list,uint32_t mask,uint32_t val)701 static int add_addresses_from_list_mask(uint8_t ** array, size_t * size, int * addr_count, int target_family, uint16_t port, struct fd_list * list, uint32_t mask, uint32_t val)
702 {
703 	struct fd_list * li;
704 	int to_add4 = 0;
705 	int to_add6 = 0;
706 	union {
707 		uint8_t *buf;
708 		sSA4	*sin;
709 		sSA6	*sin6;
710 	} ptr;
711 	size_t sz;
712 
713 	/* First, count the number of addresses to add */
714 	for (li = list->next; li != list; li = li->next) {
715 		struct fd_endpoint * ep = (struct fd_endpoint *) li;
716 
717 		/* Do the flag match ? */
718 		if ((val & mask) != (ep->flags & mask))
719 			continue;
720 
721 		if (ep->sa.sa_family == AF_INET) {
722 			to_add4 ++;
723 		} else {
724 			to_add6 ++;
725 		}
726 	}
727 
728 	if ((to_add4 + to_add6) == 0)
729 		return 0; /* nothing to do */
730 
731 	/* The size to add */
732 	if (target_family == AF_INET) {
733 		sz = to_add4 * sizeof(sSA4);
734 	} else {
735 		#ifndef SCTP_USE_MAPPED_ADDRESSES
736 			sz = (to_add4 * sizeof(sSA4)) + (to_add6 * sizeof(sSA6));
737 		#else /* SCTP_USE_MAPPED_ADDRESSES */
738 			sz = (to_add4 + to_add6) * sizeof(sSA6);
739 		#endif /* SCTP_USE_MAPPED_ADDRESSES */
740 	}
741 
742 	/* Now, (re)alloc the array to store the new addresses */
743 	CHECK_MALLOC( *array = realloc(*array, *size + sz) );
744 
745 	/* Finally, add the addresses */
746 	for (li = list->next; li != list; li = li->next) {
747 		struct fd_endpoint * ep = (struct fd_endpoint *) li;
748 
749 		/* Skip v6 addresses for v4 socket */
750 		if ((target_family == AF_INET) && (ep->sa.sa_family == AF_INET6))
751 			continue;
752 
753 		/* Are the flags matching ? */
754 		if ((val & mask) != (ep->flags & mask))
755 			continue;
756 
757 		/* Size of the new SA we are adding (array may contain a mix of sockaddr_in and sockaddr_in6) */
758 		#ifndef SCTP_USE_MAPPED_ADDRESSES
759 		if (ep->sa.sa_family == AF_INET6)
760 		#else /* SCTP_USE_MAPPED_ADDRESSES */
761 		if (target_family == AF_INET6)
762 		#endif /* SCTP_USE_MAPPED_ADDRESSES */
763 			sz = sizeof(sSA6);
764 		else
765 			sz = sizeof(sSA4);
766 
767 		/* Place where we add the new address */
768 		ptr.buf = *array + *size; /* place of the new SA */
769 
770 		/* Update other information */
771 		*size += sz;
772 		*addr_count += 1;
773 
774 		/* And write the addr in the buffer */
775 		if (sz == sizeof(sSA4)) {
776 			memcpy(ptr.buf, &ep->sin, sz);
777 			ptr.sin->sin_port = port;
778 		} else {
779 			if (ep->sa.sa_family == AF_INET) { /* We must map the address */
780 				memset(ptr.buf, 0, sz);
781 				ptr.sin6->sin6_family = AF_INET6;
782 				IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
783 			} else {
784 				memcpy(ptr.sin6, &ep->sin6, sz);
785 			}
786 			ptr.sin6->sin6_port = port;
787 		}
788 	}
789 
790 	return 0;
791 }
792 
793 /* Create a socket server and bind it according to daemon s configuration */
fd_sctp_create_bind_server(int * sock,int family,struct fd_list * list,uint16_t port)794 int fd_sctp_create_bind_server( int * sock, int family, struct fd_list * list, uint16_t port )
795 {
796 	int bind_default;
797 
798 	TRACE_ENTRY("%p %i %p %hu", sock, family, list, port);
799 	CHECK_PARAMS(sock);
800 
801 	/* Create the socket */
802 	CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
803 
804 	/* Set pre-binding socket options, including number of streams etc... */
805 	CHECK_FCT( fd_setsockopt_prebind(*sock) );
806 
807 	bind_default = (! list) || (FD_IS_LIST_EMPTY(list)) ;
808 redo:
809 	if ( bind_default ) {
810 		/* Implicit endpoints : bind to default addresses */
811 		union {
812 			sSS  ss;
813 			sSA  sa;
814 			sSA4 sin;
815 			sSA6 sin6;
816 		} s;
817 
818 		/* 0.0.0.0 and [::] are all zeros */
819 		memset(&s, 0, sizeof(s));
820 
821 		s.sa.sa_family = family;
822 
823 		if (family == AF_INET)
824 			s.sin.sin_port = htons(port);
825 		else
826 			s.sin6.sin6_port = htons(port);
827 
828 		CHECK_SYS( bind(*sock, &s.sa, sSAlen(&s)) );
829 
830 	} else {
831 		/* Explicit endpoints to bind to from config */
832 
833 		sSA * sar = NULL; /* array of addresses */
834 		size_t sz = 0; /* size of the array */
835 		int count = 0; /* number of sock addr in the array */
836 
837 		/* Create the array of configured addresses */
838 		CHECK_FCT( add_addresses_from_list_mask((void *)&sar, &sz, &count, family, htons(port), list, EP_FL_CONF, EP_FL_CONF) );
839 
840 		if (!count) {
841 			/* None of the addresses in the list came from configuration, we bind to default */
842 			bind_default = 1;
843 			goto redo;
844 		}
845 
846 		/* Debug: show bound addresses */
847 		{
848 			char * buf = NULL;
849 			size_t len = 0;
850 			CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, sar, count), );
851 			LOG_D("SCTP server binding local addresses: %s", buf);
852 			free(buf);
853 		}
854 
855 		/* Bind to this array */
856 		CHECK_SYS(  sctp_bindx(*sock, sar, count, SCTP_BINDX_ADD_ADDR)  );
857 
858 		/* We don't need sar anymore */
859 		free(sar);
860 	}
861 
862 	/* Now, the server is bound, set remaining sockopt */
863 	CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) );
864 
865 	/* Debug: show all local listening addresses */
866 	{
867 		sSA *sar = NULL;
868 		int sz = 0;
869 		char * buf = NULL;
870 		size_t len = 0;
871 
872 		CHECK_SYS(  sz = sctp_getladdrs(*sock, 0, &sar)  );
873 
874 		CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, sar, sz), );
875 		LOG_D("SCTP server locally bound addresses: %s", buf);
876 		sctp_freeladdrs(sar);
877 		free(buf);
878 	}
879 
880 	return 0;
881 }
882 
883 /* Allow clients connections on server sockets */
fd_sctp_listen(int sock)884 int fd_sctp_listen( int sock )
885 {
886 	TRACE_ENTRY("%d", sock);
887 	CHECK_SYS( listen(sock, 5) );
888 	return 0;
889 }
890 
891 /* Create a client socket and connect to remote server */
fd_sctp_client(int * sock,int no_ip6,uint16_t port,struct fd_list * list,struct fd_list * src_list)892 int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list, struct fd_list * src_list )
893 {
894 	int family;
895 	union {
896 		uint8_t *buf;
897 		sSA	*sa;
898 	} sar;
899 	size_t size = 0;
900 	int count = 0;
901 	int ret;
902 	int bind_default = 1;	/* enable ASCONF in postbind */
903 
904 	sar.buf = NULL;
905 
906 	TRACE_ENTRY("%p %i %hu %p %p", sock, no_ip6, port, list, src_list);
907 	CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) );
908 	CHECK_PARAMS( !src_list || (src_list && (!FD_IS_LIST_EMPTY(src_list))) );
909 
910 	if (no_ip6) {
911 		family = AF_INET;
912 	} else {
913 		family = AF_INET6;
914 	}
915 
916 	/* Create the socket */
917 	CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
918 
919 	/* Cleanup if we are cancelled */
920 	pthread_cleanup_push(fd_cleanup_socket, sock);
921 
922 	/* Set the socket options */
923 	CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto out );
924 
925 	/* Bind to explicit source addresses if requested */
926 	if (src_list && !FD_IS_LIST_EMPTY(src_list)) {
927 		sSA * bindsar = NULL; /* array of addresses */
928 		size_t sz = 0; /* size of the array */
929 		int sarcount = 0; /* number of sock addr in the array */
930 
931 		/* Create the array of configured addresses */
932 		CHECK_FCT_DO( ret = add_addresses_from_list_mask((void *)&bindsar, &sz, &sarcount, family, 0, src_list, EP_FL_CONF, EP_FL_CONF), goto out );
933 
934 		if (sarcount) {
935 			char * buf = NULL;
936 			size_t len = 0;
937 			CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, bindsar, sarcount), goto out );
938 			LOG_A("SCTP client binding local addresses: %s", buf);
939 			free(buf);
940 
941 			CHECK_SYS_DO( ret = sctp_bindx(*sock, bindsar, sarcount, SCTP_BINDX_ADD_ADDR), goto out );
942 		}
943 
944 		/* Disable ASCONF option in postbind */
945 		bind_default = 0;
946 
947 		/* We don't need bindsar anymore */
948 		free(bindsar);
949 	}
950 
951 	/* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */
952 	CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF,              EP_FL_CONF	), goto out );
953 	CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC	), goto out );
954 	CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0		), goto out );
955 
956 	/* Try connecting */
957 	{
958 		char * buf = NULL;
959 		size_t len = 0;
960 		CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, sar.sa, count), goto out );
961 		LOG_A("SCTP client connecting to addresses: %s", buf);
962 		free(buf);
963 	}
964 
965 	/* Bug in some Linux kernel, the sctp_connectx is not a cancellation point. To avoid blocking freeDiameter, we allow async cancel here */
966 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
967 #ifdef SCTP_CONNECTX_4_ARGS
968 	ret = sctp_connectx(*sock, sar.sa, count, NULL);
969 #else /* SCTP_CONNECTX_4_ARGS */
970 	ret = sctp_connectx(*sock, sar.sa, count);
971 #endif /* SCTP_CONNECTX_4_ARGS */
972 	/* back to normal cancelation behabior */
973 	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
974 
975 	if (ret < 0) {
976 		ret = errno;
977 		/* Some errors are expected, we log at different level */
978 		LOG_A("sctp_connectx returned an error: %s", strerror(ret));
979 		goto out;
980 	}
981 
982 	free(sar.buf); sar.buf = NULL;
983 
984 	/* Set the remaining sockopts */
985 	CHECK_FCT_DO( ret = fd_setsockopt_postbind(*sock, bind_default),
986 		{
987 			CHECK_SYS_DO( shutdown(*sock, SHUT_RDWR), /* continue */ );
988 		} );
989 
990 out:
991 	;
992 	pthread_cleanup_pop(0);
993 
994 	if (ret) {
995 		if (*sock > 0) {
996 			CHECK_SYS_DO( close(*sock), /* continue */ );
997 			*sock = -1;
998 		}
999 		free(sar.buf);
1000 	}
1001 	return ret;
1002 }
1003 
1004 /* Retrieve streams information from a connected association -- optionally provide the primary address */
fd_sctp_get_str_info(int sock,uint16_t * in,uint16_t * out,sSS * primary)1005 int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary )
1006 {
1007 	struct sctp_status status;
1008 	socklen_t sz = sizeof(status);
1009 
1010 	TRACE_ENTRY("%d %p %p %p", sock, in, out, primary);
1011 	CHECK_PARAMS( (sock > 0) && in && out );
1012 
1013 	/* Read the association parameters */
1014 	memset(&status, 0, sizeof(status));
1015 	CHECK_SYS(  getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &sz) );
1016 	if (sz != sizeof(status))
1017 	{
1018 		TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %zd", sz, sizeof(status));
1019 		return ENOTSUP;
1020 	}
1021 #if 0
1022 		char sa_buf[sSA_DUMP_STRLEN];
1023 		fd_sa_sdump_numeric(sa_buf, (sSA *)&status.sstat_primary.spinfo_address);
1024 		fd_log_debug( "SCTP_STATUS : sstat_state                  : %i" , status.sstat_state);
1025 		fd_log_debug( "              sstat_rwnd  	          : %u" , status.sstat_rwnd);
1026 		fd_log_debug( "		     sstat_unackdata	          : %hu", status.sstat_unackdata);
1027 		fd_log_debug( "		     sstat_penddata 	          : %hu", status.sstat_penddata);
1028 		fd_log_debug( "		     sstat_instrms  	          : %hu", status.sstat_instrms);
1029 		fd_log_debug( "		     sstat_outstrms 	          : %hu", status.sstat_outstrms);
1030 		fd_log_debug( "		     sstat_fragmentation_point    : %u" , status.sstat_fragmentation_point);
1031 		fd_log_debug( "		     sstat_primary.spinfo_address : %s" , sa_buf);
1032 		fd_log_debug( "		     sstat_primary.spinfo_state   : %d" , status.sstat_primary.spinfo_state);
1033 		fd_log_debug( "		     sstat_primary.spinfo_cwnd    : %u" , status.sstat_primary.spinfo_cwnd);
1034 		fd_log_debug( "		     sstat_primary.spinfo_srtt    : %u" , status.sstat_primary.spinfo_srtt);
1035 		fd_log_debug( "		     sstat_primary.spinfo_rto     : %u" , status.sstat_primary.spinfo_rto);
1036 		fd_log_debug( "		     sstat_primary.spinfo_mtu     : %u" , status.sstat_primary.spinfo_mtu);
1037 #endif /* 0 */
1038 
1039 	*in = status.sstat_instrms;
1040 	*out = status.sstat_outstrms;
1041 
1042 	if (primary)
1043 		memcpy(primary, &status.sstat_primary.spinfo_address, sizeof(sSS));
1044 
1045 	return 0;
1046 }
1047 
1048 /* Get the list of remote endpoints of the socket */
fd_sctp_get_remote_ep(int sock,struct fd_list * list)1049 int fd_sctp_get_remote_ep(int sock, struct fd_list * list)
1050 {
1051 	union {
1052 		sSA	*sa;
1053 		uint8_t	*buf;
1054 	} ptr;
1055 
1056 	sSA * data = NULL;
1057 	int count;
1058 
1059 	TRACE_ENTRY("%d %p", sock, list);
1060 	CHECK_PARAMS(list);
1061 
1062 	/* Read the list on the socket */
1063 	CHECK_SYS( count = sctp_getpaddrs(sock, 0, &data)  );
1064 	ptr.sa = data;
1065 
1066 	while (count) {
1067 		socklen_t sl;
1068 		switch (ptr.sa->sa_family) {
1069 			case AF_INET:	sl = sizeof(sSA4); break;
1070 			case AF_INET6:	sl = sizeof(sSA6); break;
1071 			default:
1072 				TRACE_DEBUG(INFO, "Unknown address family returned in sctp_getpaddrs: %d, skip", ptr.sa->sa_family);
1073 				/* There is a bug in current Linux kernel: http://www.spinics.net/lists/linux-sctp/msg00760.html */
1074 				goto stop;
1075 		}
1076 
1077 		CHECK_FCT( fd_ep_add_merge( list, ptr.sa, sl, EP_FL_LL ) );
1078 		ptr.buf += sl;
1079 		count --;
1080 	}
1081 stop:
1082 	/* Free the list */
1083 	sctp_freepaddrs(data);
1084 
1085 	/* Now get the primary address, the add function will take care of merging with existing entry */
1086 	{
1087 
1088 		struct sctp_status status;
1089 		socklen_t sz = sizeof(status);
1090 		int ret;
1091 
1092 		memset(&status, 0, sizeof(status));
1093 		/* Attempt to use SCTP_STATUS message to retrieve the primary address */
1094 		CHECK_SYS_DO( ret = getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &sz), /* continue */);
1095 		if (sz != sizeof(status))
1096 			ret = -1;
1097 		sz = sizeof(sSS);
1098 		if (ret < 0)
1099 		{
1100 			/* Fallback to getsockname -- not recommended by draft-ietf-tsvwg-sctpsocket-19#section-7.4 */
1101 			CHECK_SYS(getpeername(sock, (sSA *)&status.sstat_primary.spinfo_address, &sz));
1102 		}
1103 
1104 		CHECK_FCT( fd_ep_add_merge( list, (sSA *)&status.sstat_primary.spinfo_address, sz, EP_FL_PRIMARY ) );
1105 	}
1106 
1107 	/* Done! */
1108 	return 0;
1109 }
1110 
1111 /* Send a vector over a specified stream */
fd_sctp_sendstrv(struct cnxctx * conn,uint16_t strid,const struct iovec * iov,int iovcnt)1112 ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt)
1113 {
1114 	struct msghdr mhdr;
1115 	struct cmsghdr 		*hdr;
1116 #ifdef OLD_SCTP_SOCKET_API
1117 	struct sctp_sndrcvinfo	*sndrcv;
1118 	uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1119 #else /* OLD_SCTP_SOCKET_API */
1120 	struct sctp_sndinfo 	*sndinf;
1121 	uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
1122 #endif /* OLD_SCTP_SOCKET_API */
1123 	ssize_t ret;
1124 	struct timespec ts, now;
1125 
1126 	TRACE_ENTRY("%p %hu %p %d", conn, strid, iov, iovcnt);
1127 	CHECK_PARAMS_DO(conn && iov && iovcnt, { errno = EINVAL; return -1; } );
1128 	CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &ts), return -1 );
1129 
1130 	memset(&mhdr, 0, sizeof(mhdr));
1131 	memset(&anci, 0, sizeof(anci));
1132 
1133 	/* Anciliary data: specify SCTP stream */
1134 	hdr = (struct cmsghdr *)anci;
1135 	hdr->cmsg_len   = sizeof(anci);
1136 	hdr->cmsg_level = IPPROTO_SCTP;
1137 #ifdef OLD_SCTP_SOCKET_API
1138 	hdr->cmsg_type  = SCTP_SNDRCV;
1139 	sndrcv = (struct sctp_sndrcvinfo *)CMSG_DATA(hdr);
1140 	sndrcv->sinfo_stream = strid;
1141 #else /* OLD_SCTP_SOCKET_API */
1142 	hdr->cmsg_type  = SCTP_SNDINFO;
1143 	sndinf = (struct sctp_sndinfo *)CMSG_DATA(hdr);
1144 	sndinf->snd_sid = strid;
1145 #endif /* OLD_SCTP_SOCKET_API */
1146 	/* note : we could store other data also, for example in .sinfo_ppid for remote peer or in .sinfo_context for errors. */
1147 
1148 	/* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */
1149 
1150 	mhdr.msg_iov    = (struct iovec *)iov;
1151 	mhdr.msg_iovlen = iovcnt;
1152 
1153 	mhdr.msg_control    = anci;
1154 	mhdr.msg_controllen = sizeof(anci);
1155 
1156 	TRACE_DEBUG(FULL, "Sending %d chunks of data (first:%zdb) on stream %hu of socket %d", iovcnt, iov[0].iov_len, strid, conn->cc_socket);
1157 again:
1158 	ret = sendmsg(conn->cc_socket, &mhdr, 0);
1159 	/* Handle special case of timeout */
1160 	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
1161 		pthread_testcancel();
1162 		/* Check how much time we were blocked for this sending. */
1163 		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now), return -1 );
1164 		if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
1165 			LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME);
1166 		} else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
1167 			goto again; /* don't care, just ignore */
1168 		}
1169 
1170 		/* propagate the error */
1171 		errno = -ret;
1172 		ret = -1;
1173 	}
1174 
1175 	CHECK_SYS_DO( ret, ); /* for tracing error only */
1176 
1177 	return ret;
1178 }
1179 
1180 /* Receive the next data from the socket, or next notification */
fd_sctp_recvmeta(struct cnxctx * conn,uint16_t * strid,uint8_t ** buf,size_t * len,int * event)1181 int fd_sctp_recvmeta(struct cnxctx * conn, uint16_t * strid, uint8_t ** buf, size_t * len, int *event)
1182 {
1183 	ssize_t 		 ret = 0;
1184 	struct msghdr 		 mhdr;
1185 	char   			 ancidata[ CMSG_BUF_LEN ];
1186 	struct iovec 		 iov;
1187 	uint8_t			*data = NULL;
1188 	size_t 			 bufsz = 0, datasize = 0;
1189 	size_t			 mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */
1190 	int 			 timedout = 0;
1191 
1192 	TRACE_ENTRY("%p %p %p %p %p", conn, strid, buf, len, event);
1193 	CHECK_PARAMS( conn && buf && len && event );
1194 
1195 	/* Cleanup out parameters */
1196 	*buf = NULL;
1197 	*len = 0;
1198 	*event = 0;
1199 
1200 	/* Prepare header for receiving message */
1201 	memset(&mhdr, 0, sizeof(mhdr));
1202 	mhdr.msg_iov    = &iov;
1203 	mhdr.msg_iovlen = 1;
1204 	mhdr.msg_control    = &ancidata;
1205 	mhdr.msg_controllen = sizeof(ancidata);
1206 
1207 next_message:
1208 	datasize = 0;
1209 
1210 	/* We will loop while all data is not received. */
1211 incomplete:
1212 	while (datasize >= bufsz ) {
1213 		/* The buffer is full, enlarge it */
1214 		bufsz += mempagesz;
1215 		CHECK_MALLOC( data = realloc(data, bufsz ) );
1216 	}
1217 	/* the new data will be received following the preceding */
1218 	memset(&iov,  0, sizeof(iov));
1219 	iov.iov_base = data + datasize ;
1220 	iov.iov_len  = bufsz - datasize;
1221 
1222 	/* Receive data from the socket */
1223 again:
1224 	pthread_cleanup_push(free, data);
1225 	ret = recvmsg(conn->cc_socket, &mhdr, 0);
1226 	pthread_testcancel();
1227 	pthread_cleanup_pop(0);
1228 
1229 	/* First, handle timeouts (same as fd_cnx_s_recv) */
1230 	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
1231 		if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING ))
1232 			goto again; /* don't care, just ignore */
1233 		if (!timedout) {
1234 			timedout ++; /* allow for one timeout while closing */
1235 			goto again;
1236 		}
1237 		/* fallback to normal handling */
1238 	}
1239 
1240 	/* Handle errors */
1241 	if (ret <= 0) { /* Socket timedout, closed, or an error occurred */
1242 		CHECK_SYS_DO(ret, /* to log in case of error */);
1243 		free(data);
1244 		*event = FDEVP_CNX_ERROR;
1245 		return 0;
1246 	}
1247 
1248 	/* Update the size of data we received */
1249 	datasize += ret;
1250 
1251 	/* SCTP provides an indication when we received a full record; loop if it is not the case */
1252 	if ( ! (mhdr.msg_flags & MSG_EOR) ) {
1253 		goto incomplete;
1254 	}
1255 
1256 	/* Handle the case where the data received is a notification */
1257 	if (mhdr.msg_flags & MSG_NOTIFICATION) {
1258 		union sctp_notification * notif = (union sctp_notification *) data;
1259 		char sa_buf[sSA_DUMP_STRLEN];
1260 
1261 		TRACE_DEBUG(FULL, "Received %zdb data of notification on socket %d", datasize, conn->cc_socket);
1262 
1263 		switch (notif->sn_header.sn_type) {
1264 
1265 			case SCTP_ASSOC_CHANGE: /* We should not receive these as we did not subscribe for it */
1266 				TRACE_DEBUG(FULL, "Received SCTP_ASSOC_CHANGE notification");
1267 				TRACE_DEBUG(ANNOYING, "    state : %hu", notif->sn_assoc_change.sac_state);
1268 				TRACE_DEBUG(ANNOYING, "    error : %hu", notif->sn_assoc_change.sac_error);
1269 				TRACE_DEBUG(ANNOYING, "    instr : %hu", notif->sn_assoc_change.sac_inbound_streams);
1270 				TRACE_DEBUG(ANNOYING, "   outstr : %hu", notif->sn_assoc_change.sac_outbound_streams);
1271 
1272 				*event = FDEVP_CNX_EP_CHANGE;
1273 				break;
1274 
1275 			case SCTP_PEER_ADDR_CHANGE:
1276 				TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification");
1277 				fd_sa_sdump_numeric(sa_buf, (sSA *)&(notif->sn_paddr_change.spc_aaddr));
1278 				TRACE_DEBUG(ANNOYING, "    intf_change : %s", sa_buf);
1279 				TRACE_DEBUG(ANNOYING, "          state : %d", notif->sn_paddr_change.spc_state);
1280 				TRACE_DEBUG(ANNOYING, "          error : %d", notif->sn_paddr_change.spc_error);
1281 
1282 				*event = FDEVP_CNX_EP_CHANGE;
1283 				break;
1284 
1285 			case SCTP_REMOTE_ERROR:
1286 				TRACE_DEBUG(FULL, "Received SCTP_REMOTE_ERROR notification");
1287 				TRACE_DEBUG(ANNOYING, "    err : %hu", ntohs(notif->sn_remote_error.sre_error));
1288 				TRACE_DEBUG(ANNOYING, "    len : %hu", ntohs(notif->sn_remote_error.sre_length));
1289 
1290 				*event = FDEVP_CNX_ERROR;
1291 				break;
1292 
1293 #ifdef OLD_SCTP_SOCKET_API
1294 			case SCTP_SEND_FAILED:
1295 				TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED notification");
1296 				TRACE_DEBUG(ANNOYING, "    len : %hu", notif->sn_send_failed.ssf_length);
1297 				TRACE_DEBUG(ANNOYING, "    err : %d",  notif->sn_send_failed.ssf_error);
1298 
1299 				*event = FDEVP_CNX_ERROR;
1300 				break;
1301 #else /*  OLD_SCTP_SOCKET_API */
1302 			case SCTP_SEND_FAILED_EVENT:
1303 				TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED_EVENT notification");
1304 				*event = FDEVP_CNX_ERROR;
1305 				break;
1306 #endif	/*  OLD_SCTP_SOCKET_API */
1307 			case SCTP_SHUTDOWN_EVENT:
1308 				TRACE_DEBUG(FULL, "Received SCTP_SHUTDOWN_EVENT notification");
1309 
1310 				*event = FDEVP_CNX_SHUTDOWN;
1311 				break;
1312 
1313 #ifndef OLD_SCTP_SOCKET_API
1314 #ifdef SCTP_NOTIFICATIONS_STOPPED_EVENT
1315 			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
1316 				TRACE_DEBUG(INFO, "Received SCTP_NOTIFICATIONS_STOPPED_EVENT notification, marking the association in error state");
1317 				*event = FDEVP_CNX_ERROR;
1318 				break;
1319 #endif	/*  SCTP_NOTIFICATIONS_STOPPED_EVENT  */
1320 #endif	/*  OLD_SCTP_SOCKET_API */
1321 
1322 			default:
1323 				TRACE_DEBUG(FULL, "Received unknown notification %d, ignored", notif->sn_header.sn_type);
1324 				goto next_message;
1325 		}
1326 
1327 		free(data);
1328 		return 0;
1329 	}
1330 
1331 	/* From this point, we have received a message */
1332 	*event = FDEVP_CNX_MSG_RECV;
1333 	*buf = data;
1334 	*len = datasize;
1335 
1336 	if (strid) {
1337 		struct cmsghdr 		*hdr;
1338 #ifdef OLD_SCTP_SOCKET_API
1339 		struct sctp_sndrcvinfo	*sndrcv;
1340 #else /*  OLD_SCTP_SOCKET_API */
1341 		struct sctp_rcvinfo	*rcvinf;
1342 #endif /*  OLD_SCTP_SOCKET_API */
1343 
1344 		/* Handle the anciliary data */
1345 		for (hdr = CMSG_FIRSTHDR(&mhdr); hdr; hdr = CMSG_NXTHDR(&mhdr, hdr)) {
1346 
1347 			/* We deal only with anciliary data at SCTP level */
1348 			if (hdr->cmsg_level != IPPROTO_SCTP) {
1349 				TRACE_DEBUG(FULL, "Received some anciliary data at level %d, skipped", hdr->cmsg_level);
1350 				continue;
1351 			}
1352 
1353 #ifdef OLD_SCTP_SOCKET_API
1354 			/* Also only interested in SCTP_SNDRCV message for the moment */
1355 			if (hdr->cmsg_type != SCTP_SNDRCV) {
1356 				TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
1357 				continue;
1358 			}
1359 
1360 			sndrcv = (struct sctp_sndrcvinfo *) CMSG_DATA(hdr);
1361 			if (TRACE_BOOL(ANNOYING)) {
1362 				fd_log_debug( "Anciliary block IPPROTO_SCTP / SCTP_SNDRCV");
1363 				fd_log_debug( "    sinfo_stream    : %hu", sndrcv->sinfo_stream);
1364 				fd_log_debug( "    sinfo_ssn       : %hu", sndrcv->sinfo_ssn);
1365 				fd_log_debug( "    sinfo_flags     : %hu", sndrcv->sinfo_flags);
1366 				/* fd_log_debug( "    sinfo_pr_policy : %hu", sndrcv->sinfo_pr_policy); */
1367 				fd_log_debug( "    sinfo_ppid      : %u" , sndrcv->sinfo_ppid);
1368 				fd_log_debug( "    sinfo_context   : %u" , sndrcv->sinfo_context);
1369 				/* fd_log_debug( "    sinfo_pr_value  : %u" , sndrcv->sinfo_pr_value); */
1370 				fd_log_debug( "    sinfo_tsn       : %u" , sndrcv->sinfo_tsn);
1371 				fd_log_debug( "    sinfo_cumtsn    : %u" , sndrcv->sinfo_cumtsn);
1372 			}
1373 
1374 			*strid = sndrcv->sinfo_stream;
1375 #else /*  OLD_SCTP_SOCKET_API */
1376 			/* Also only interested in SCTP_RCVINFO message for the moment */
1377 			if (hdr->cmsg_type != SCTP_RCVINFO) {
1378 				TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
1379 				continue;
1380 			}
1381 
1382 			rcvinf = (struct sctp_rcvinfo *) CMSG_DATA(hdr);
1383 
1384 			*strid = rcvinf->rcv_sid;
1385 #endif /*  OLD_SCTP_SOCKET_API */
1386 
1387 
1388 		}
1389 		TRACE_DEBUG(FULL, "Received %zdb data on socket %d, stream %hu", datasize, conn->cc_socket, *strid);
1390 	} else {
1391 		TRACE_DEBUG(FULL, "Received %zdb data on socket %d (stream ignored)", datasize, conn->cc_socket);
1392 	}
1393 
1394 	return 0;
1395 }
1396