1 /*
2 * $Id$
3 *
4 * SocketAPI implementation for the sctplib.
5 * Copyright (C) 1999-2020 by Thomas Dreibholz
6 *
7 * Realized in co-operation between
8 * - Siemens AG
9 * - University of Essen, Institute of Computer Networking Technology
10 * - University of Applied Sciences, Muenster
11 *
12 * Acknowledgement
13 * This work was partially funded by the Bundesministerium fuer Bildung und
14 * Forschung (BMBF) of the Federal Republic of Germany (Foerderkennzeichen 01AK045).
15 * The authors alone are responsible for the contents.
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 * Contact: discussion@sctp.de
31 * dreibh@iem.uni-due.de
32 * tuexen@fh-muenster.de
33 *
34 * Purpose: SCTP Socket Wrapper
35 *
36 */
37
38 #include "tdsystem.h"
39 #include "sctpsocketwrapper.h"
40 #include "extsocketdescriptor.h"
41 #include "tdin6.h"
42
43 #include <stdarg.h>
44 #include <sys/ioctl.h>
45 #include <poll.h>
46
47
48 // Random port selection for INADDR_ANY. Necessary for localhost testing!
49 #define RANDOM_PORTSELECTION
50
51 // Print note, if no SCTP is available in kernel.
52 // #define PRINT_NOSCTP_NOTE
53 // #define PRINT_RANDOM_PORTSELECTION
54 // #define PRINT_SELECT
55
56
57
58 #ifndef HAVE_KERNEL_SCTP
59
60
61 #include "tdmessage.h"
62 #include "internetaddress.h"
63 #include "sctpsocketmaster.h"
64 #include "sctpsocket.h"
65 #include "sctpassociation.h"
66
67
68 #include <sys/time.h>
69 #include <sys/uio.h>
70 #include <sys/types.h>
71 #include <sys/socket.h>
72
73 #if (SYSTEM == OS_SOLARIS)
74 #include <sys/stat.h>
75 #include <fcntl.h>
76 #endif
77 // Set errno variable and return.
getErrnoResult(const int result)78 inline static int getErrnoResult(const int result)
79 {
80 if(result < 0) {
81 errno = -result;
82 return(-1);
83 }
84 // errno = 0;
85 return(result);
86 }
87 #define errno_return(x) return(getErrnoResult(x))
88
89
90 // FD_ISSET rewriting with NULL check
SAFE_FD_ISSET(int fd,fd_set * fdset)91 inline static int SAFE_FD_ISSET(int fd, fd_set* fdset)
92 {
93 if(fdset == NULL) {
94 return(0);
95 }
96 return(FD_ISSET(fd,fdset));
97 }
98
99
100 // FD_ZERO rewriting with NULL check
SAFE_FD_ZERO(fd_set * fdset)101 inline static void SAFE_FD_ZERO(fd_set* fdset)
102 {
103 if(fdset != NULL) {
104 FD_ZERO(fdset);
105 }
106 }
107
108
109 // ###### Unpack sockaddr blocks to sockaddr_storage array ##################
unpack_sockaddr(const sockaddr * addrArray,const size_t addrs,sockaddr_storage * newArray)110 static void unpack_sockaddr(const sockaddr* addrArray,
111 const size_t addrs,
112 sockaddr_storage* newArray)
113 {
114 for(size_t i = 0;i < addrs;i++) {
115 switch(addrArray->sa_family) {
116 case AF_INET:
117 memcpy((void*)&newArray[i], addrArray, sizeof(struct sockaddr_in));
118 addrArray = (sockaddr*)((long)addrArray + (long)sizeof(sockaddr_in));
119 break;
120 case AF_INET6:
121 memcpy((void*)&newArray[i], addrArray, sizeof(struct sockaddr_in6));
122 addrArray = (sockaddr*)((long)addrArray + (long)sizeof(sockaddr_in6));
123 break;
124 default:
125 std::cerr << "ERROR: unpack_sockaddr() - Unknown address type #" << addrArray->sa_family << "!" << std::endl;
126 abort();
127 break;
128 }
129 }
130 }
131
132
133 // ###### Pack sockaddr_storage array to sockaddr blocks ####################
pack_sockaddr_storage(const sockaddr_storage * addrArray,const size_t addrs)134 static sockaddr* pack_sockaddr_storage(const sockaddr_storage* addrArray, const size_t addrs)
135 {
136 size_t required = 0;
137 for(size_t i = 0;i < addrs;i++) {
138 switch(((sockaddr*)&addrArray[i])->sa_family) {
139 case AF_INET:
140 required += sizeof(struct sockaddr_in);
141 break;
142 case AF_INET6:
143 required += sizeof(struct sockaddr_in6);
144 break;
145 default:
146 std::cerr << "ERROR: pack_sockaddr_storage() - Unknown address type #" << ((sockaddr*)&addrArray[i])->sa_family << "!" << std::endl;
147 abort();
148 break;
149 }
150 }
151
152 sockaddr* newArray = NULL;
153 if(required > 0) {
154 newArray = (sockaddr*)new char[required];
155 if(newArray == NULL) {
156 return(NULL);
157 }
158 sockaddr* a = newArray;
159 for(size_t i = 0;i < addrs;i++) {
160 switch(((sockaddr*)&addrArray[i])->sa_family) {
161 case AF_INET:
162 memcpy((void*)a, (void*)&addrArray[i], sizeof(struct sockaddr_in));
163 a = (sockaddr*)((long)a + (long)sizeof(sockaddr_in));
164 break;
165 case AF_INET6:
166 memcpy((void*)a, (void*)&addrArray[i], sizeof(struct sockaddr_in6));
167 a = (sockaddr*)((long)a + (long)sizeof(sockaddr_in6));
168 break;
169 }
170 }
171 }
172 return(newArray);
173 }
174
175
176
177 // ###### Constructor #######################################################
ExtSocketDescriptorMaster()178 ExtSocketDescriptorMaster::ExtSocketDescriptorMaster()
179 {
180 for(unsigned int i = 0;i < MaxSockets;i++) {
181 Sockets[i].Type = ExtSocketDescriptor::ESDT_Invalid;
182 }
183 if(STDIN_FILENO < MaxSockets) {
184 Sockets[STDIN_FILENO].Type = ExtSocketDescriptor::ESDT_System;
185 Sockets[STDIN_FILENO].Socket.SystemSocketID = STDIN_FILENO;
186 }
187 if(STDOUT_FILENO < MaxSockets) {
188 Sockets[STDOUT_FILENO].Type = ExtSocketDescriptor::ESDT_System;
189 Sockets[STDOUT_FILENO].Socket.SystemSocketID = STDOUT_FILENO;
190 }
191 if(STDERR_FILENO < MaxSockets) {
192 Sockets[STDERR_FILENO].Type = ExtSocketDescriptor::ESDT_System;
193 Sockets[STDERR_FILENO].Socket.SystemSocketID = STDERR_FILENO;
194 }
195 }
196
197
198 // ###### Destructor ########################################################
~ExtSocketDescriptorMaster()199 ExtSocketDescriptorMaster::~ExtSocketDescriptorMaster()
200 {
201 for(unsigned int i = 0;i < MaxSockets;i++) {
202 if((Sockets[i].Type != ExtSocketDescriptor::ESDT_Invalid) &&
203 (i != STDIN_FILENO) &&
204 (i != STDOUT_FILENO) &&
205 (i != STDERR_FILENO)) {
206 ext_close(i);
207 }
208 }
209 }
210
211
212 // ###### Get ExtSocketDescriptor for given ID ##############################
getSocket(const int id)213 inline ExtSocketDescriptor* ExtSocketDescriptorMaster::getSocket(const int id)
214 {
215 if((id < (int)MaxSockets) && (id >= 0)) {
216 return(&Sockets[id]);
217 }
218 return(NULL);
219 }
220
221
222 // ###### Set ExtSocketDescriptor of given ID ###############################
setSocket(const ExtSocketDescriptor & newSocket)223 int ExtSocketDescriptorMaster::setSocket(const ExtSocketDescriptor& newSocket)
224 {
225 // This operation must be atomic!
226 SCTPSocketMaster::MasterInstance.lock();
227 for(int i = (int)(std::min((int)FD_SETSIZE, getdtablesize())) - 1;i >= 0;i--) {
228 if(Sockets[i].Type == ExtSocketDescriptor::ESDT_Invalid) {
229 Sockets[i] = newSocket;
230 SCTPSocketMaster::MasterInstance.unlock();
231 return(i);
232 }
233 }
234 SCTPSocketMaster::MasterInstance.unlock();
235 return(-EMFILE);
236 }
237
238
239 // ###### Get paddrinfo #####################################################
getPrimaryAddressInfo(ExtSocketDescriptor * tdSocket,unsigned int assocID,sctp_paddrinfo & paddrinfo)240 static int getPrimaryAddressInfo(ExtSocketDescriptor* tdSocket,
241 unsigned int assocID,
242 sctp_paddrinfo& paddrinfo)
243 {
244 int result = -EBADF;
245 SCTP_PathStatus parameters;
246
247 SCTPSocketMaster::MasterInstance.lock();
248
249 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
250 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
251 getPathParameters(NULL,parameters)) {
252 assocID = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID();
253 result = 0;
254 }
255 }
256 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
257 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
258 getPathParameters(assocID,NULL,parameters)) {
259 result = 0;
260 }
261 }
262
263 if(result == 0) {
264 SocketAddress* address = SocketAddress::createSocketAddress(0,
265 (char*)¶meters.destinationAddress);
266 if(address != NULL) {
267 if(address->getSystemAddress((sockaddr*)&paddrinfo.spinfo_address,
268 sizeof(paddrinfo.spinfo_address),
269 tdSocket->Socket.SCTPSocketDesc.Domain) > 0) {
270 paddrinfo.spinfo_state = parameters.state;
271 paddrinfo.spinfo_cwnd = parameters.cwnd;
272 paddrinfo.spinfo_srtt = parameters.srtt;
273 paddrinfo.spinfo_rto = parameters.rto;
274 paddrinfo.spinfo_mtu = parameters.mtu;
275 paddrinfo.spinfo_assoc_id = assocID;
276 }
277 else {
278 result = -EIO;
279 }
280 delete address;
281 }
282 else {
283 result = -EIO;
284 }
285 }
286
287 SCTPSocketMaster::MasterInstance.unlock();
288
289 return(result);
290 }
291
292
293 // ###### Get association parameters ########################################
getAssocParams(ExtSocketDescriptor * tdSocket,unsigned int & assocID,SCTP_Association_Status & parameters)294 static int getAssocParams(ExtSocketDescriptor* tdSocket,
295 unsigned int& assocID,
296 SCTP_Association_Status& parameters)
297 {
298 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
299 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
300 getAssocStatus(parameters)) {
301 assocID = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID();
302 return(0);
303 }
304 }
305 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
306 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
307 getAssocStatus(assocID, parameters)) {
308 return(0);
309 }
310 }
311 return(-1);
312 }
313
314
315 // ###### Set association parameters ########################################
setAssocParams(ExtSocketDescriptor * tdSocket,const unsigned int assocID,const SCTP_Association_Status & parameters)316 static int setAssocParams(ExtSocketDescriptor* tdSocket,
317 const unsigned int assocID,
318 const SCTP_Association_Status& parameters)
319 {
320 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
321 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
322 setAssocStatus(parameters)) {
323 return(0);
324 }
325 }
326 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
327 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
328 setAssocStatus(assocID, parameters)) {
329 return(0);
330 }
331 }
332 return(-1);
333 }
334
335
336 // ###### Get path status ###################################################
getPathStatus(ExtSocketDescriptor * tdSocket,unsigned int & assocID,sockaddr * sockadr,const socklen_t socklen,SCTP_PathStatus & parameters)337 static int getPathStatus(ExtSocketDescriptor* tdSocket,
338 unsigned int& assocID,
339 sockaddr* sockadr,
340 const socklen_t socklen,
341 SCTP_PathStatus& parameters)
342 {
343 SocketAddress* address = SocketAddress::createSocketAddress(0,sockadr,socklen);
344 if(address == NULL) {
345 return(-EINVAL);
346 }
347
348 // ====== Get path status =============================================
349 bool ok = false;
350 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
351 ok = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getPathParameters(address,parameters);
352 }
353 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
354 ok = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getPathParameters(assocID,address,parameters);
355 }
356
357 delete address;
358 return((ok == false) ? -EIO : 0);
359 }
360
361
362 // ###### Set path status ###################################################
setPathStatus(ExtSocketDescriptor * tdSocket,unsigned int assocID,sockaddr * sockadr,const socklen_t socklen,const SCTP_PathStatus & newParameters)363 static int setPathStatus(ExtSocketDescriptor* tdSocket,
364 unsigned int assocID,
365 sockaddr* sockadr,
366 const socklen_t socklen,
367 const SCTP_PathStatus& newParameters)
368 {
369 SocketAddress* address = SocketAddress::createSocketAddress(0,sockadr,socklen);
370 if(address == NULL) {
371 return(-EINVAL);
372 }
373
374 // ====== Get path status =============================================
375 bool ok = false;
376 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
377 ok = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setPathParameters(address,newParameters);
378 }
379 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
380 ok = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setPathParameters(assocID,address,newParameters);
381 }
382
383 delete address;
384 return((ok == false) ? -EIO : 0);
385 }
386
387
388 // ###### Get version #######################################################
socketAPIGetVersion()389 unsigned int socketAPIGetVersion()
390 {
391 return((SOCKETAPI_MAJOR_VERSION << 16) | SOCKETAPI_MINOR_VERSION);
392 }
393
394
395 // ###### socket() wrapper ##################################################
ext_socket(int domain,int type,int protocol)396 int ext_socket(int domain, int type, int protocol)
397 {
398 ExtSocketDescriptor tdSocket;
399 if(protocol == IPPROTO_SCTP) {
400 // ====== Is SCTP available? ==========================================
401 if(!sctp_isavailable()) {
402 errno_return(-ENOPROTOOPT);
403 }
404
405 // ====== Check parameters ============================================
406 cardinal flags;
407 if(type == SOCK_STREAM) {
408 tdSocket.Socket.SCTPSocketDesc.ConnectionOriented = true;
409 flags = 0;
410 }
411 else if((type == SOCK_DGRAM) || (type == SOCK_SEQPACKET)) {
412 tdSocket.Socket.SCTPSocketDesc.ConnectionOriented = false;
413 flags = SCTPSocket::SSF_GlobalQueue|SCTPSocket::SSF_AutoConnect;
414 }
415 else {
416 errno_return(-EINVAL);
417 }
418
419 // ====== Create SCTP socket ==========================================
420 tdSocket.Type = ExtSocketDescriptor::ESDT_SCTP;
421 tdSocket.Socket.SCTPSocketDesc.Domain = domain;
422 tdSocket.Socket.SCTPSocketDesc.Type = type;
423 tdSocket.Socket.SCTPSocketDesc.Flags = 0;
424 tdSocket.Socket.SCTPSocketDesc.Linger.l_onoff = 1;
425 tdSocket.Socket.SCTPSocketDesc.Linger.l_linger = 10;
426 tdSocket.Socket.SCTPSocketDesc.SCTPAssociationPtr = NULL;
427 tdSocket.Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams = 10;
428 tdSocket.Socket.SCTPSocketDesc.InitMsg.sinit_max_instreams = 10;
429 tdSocket.Socket.SCTPSocketDesc.InitMsg.sinit_max_attempts = 8;
430 tdSocket.Socket.SCTPSocketDesc.InitMsg.sinit_max_init_timeo = 60000;
431 tdSocket.Socket.SCTPSocketDesc.SCTPSocketPtr = new SCTPSocket(domain, flags);
432 if(tdSocket.Socket.SCTPSocketDesc.SCTPSocketPtr == NULL) {
433 errno_return(-ENOMEM);
434 }
435
436 // Set default notifications for UDP-like socket: no notification messages
437 if(tdSocket.Socket.SCTPSocketDesc.ConnectionOriented == false) {
438 tdSocket.Socket.SCTPSocketDesc.SCTPSocketPtr->setNotificationFlags(
439 SCTP_RECVDATAIOEVNT );
440 }
441
442 int result = ExtSocketDescriptorMaster::setSocket(tdSocket);
443 if(result < 0) {
444 delete tdSocket.Socket.SCTPSocketDesc.SCTPSocketPtr;
445 tdSocket.Socket.SCTPSocketDesc.SCTPSocketPtr = NULL;
446 }
447 errno_return(result);
448 }
449 else {
450 // ====== Create system socket ========================================
451 tdSocket.Type = ExtSocketDescriptor::ESDT_System;
452 tdSocket.Socket.SystemSocketID = socket(domain,type,protocol);
453 if(tdSocket.Socket.SystemSocketID >= 0) {
454 int result = ExtSocketDescriptorMaster::setSocket(tdSocket);
455 errno_return(result);
456 }
457 errno_return(tdSocket.Socket.SystemSocketID);
458 }
459 }
460
461
462 // ###### open() wrapper ####################################################
ext_open(const char * pathname,int flags,mode_t mode)463 int ext_open(const char* pathname, int flags, mode_t mode)
464 {
465 ExtSocketDescriptor tdSocket;
466 tdSocket.Type = ExtSocketDescriptor::ESDT_System;
467 tdSocket.Socket.SystemSocketID = open(pathname,flags,mode);
468 if(tdSocket.Socket.SystemSocketID >= 0) {
469 int result = ExtSocketDescriptorMaster::setSocket(tdSocket);
470 if(result < 0) {
471 close(tdSocket.Socket.SystemSocketID);
472 }
473 errno_return(result);
474 }
475 errno_return(tdSocket.Socket.SystemSocketID);
476 }
477
478
479 // ###### creat() wrapper ###################################################
ext_creat(const char * pathname,mode_t mode)480 int ext_creat(const char* pathname, mode_t mode)
481 {
482 ExtSocketDescriptor tdSocket;
483 tdSocket.Type = ExtSocketDescriptor::ESDT_System;
484 tdSocket.Socket.SystemSocketID = creat(pathname,mode);
485 if(tdSocket.Socket.SystemSocketID >= 0) {
486 int result = ExtSocketDescriptorMaster::setSocket(tdSocket);
487 if(result < 0) {
488 close(tdSocket.Socket.SystemSocketID);
489 }
490 errno_return(result);
491 }
492 errno_return(tdSocket.Socket.SystemSocketID);
493 }
494
495
496 // ###### pipe() wrapper ####################################################
ext_pipe(int fds[2])497 int ext_pipe(int fds[2])
498 {
499 ExtSocketDescriptor tdSocket1;
500 ExtSocketDescriptor tdSocket2;
501 int newPipe[2];
502
503 if(pipe((int*)&newPipe) == 0) {
504 tdSocket1.Type = ExtSocketDescriptor::ESDT_System;
505 tdSocket1.Socket.SystemSocketID = newPipe[0];
506 tdSocket2.Type = ExtSocketDescriptor::ESDT_System;
507 tdSocket2.Socket.SystemSocketID = newPipe[1];
508
509 fds[0] = ExtSocketDescriptorMaster::setSocket(tdSocket1);
510 if(fds[0] < 0) {
511 close(tdSocket1.Socket.SystemSocketID);
512 close(tdSocket2.Socket.SystemSocketID);
513 errno_return(fds[0]);
514 }
515 fds[1] = ExtSocketDescriptorMaster::setSocket(tdSocket2);
516 if(fds[1] < 0) {
517 ext_close(fds[0]);
518 close(tdSocket2.Socket.SystemSocketID);
519 errno_return(fds[1]);
520 }
521 errno_return(0);
522 }
523 return(-1);
524 }
525
526
527 // ###### Check whether the SCTP socket is still referenced #######
mayRemoveSocket(ExtSocketDescriptor * tdSocket)528 static bool mayRemoveSocket(ExtSocketDescriptor* tdSocket)
529 {
530 const SCTPSocket* sctpSocket = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr;
531
532 for(unsigned int i = 1;i <= ExtSocketDescriptorMaster::MaxSockets;i++) {
533 ExtSocketDescriptor* td = ExtSocketDescriptorMaster::getSocket(i);
534 if((td != NULL) &&
535 (td != tdSocket) &&
536 (td->Type == ExtSocketDescriptor::ESDT_SCTP) &&
537 (td->Socket.SCTPSocketDesc.SCTPSocketPtr == sctpSocket)) {
538 return(false);
539 }
540 }
541 return(true);
542 }
543
544
545 // ###### close() wrapper ###################################################
ext_close(int sockfd)546 int ext_close(int sockfd)
547 {
548 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
549 if(tdSocket != NULL) {
550 SCTPSocketMaster::MasterInstance.lock();
551
552 switch(tdSocket->Type) {
553 case ExtSocketDescriptor::ESDT_SCTP:
554 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
555 if(tdSocket->Socket.SCTPSocketDesc.Linger.l_onoff == 1) {
556 if(tdSocket->Socket.SCTPSocketDesc.Linger.l_linger > 0) {
557 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->shutdown();
558 }
559 else {
560 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->abort();
561 }
562 }
563 delete tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr;
564 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr = NULL;
565 }
566 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
567 if(mayRemoveSocket(tdSocket)) {
568 if(tdSocket->Socket.SCTPSocketDesc.Linger.l_onoff == 1) {
569 if(tdSocket->Socket.SCTPSocketDesc.Linger.l_linger > 0) {
570 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->unbind(false);
571 }
572 else {
573 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->unbind(true);
574 }
575 }
576 delete tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr;
577 }
578 else {
579 /* ext_close() has been invoked on a peeled-off socket.
580 The SCTPSocket object will be deleted when closing the last socket. */
581 // std::cerr << "INFO: ext_close(" << sockfd << ") - still in use. OK!" << std::endl;
582 }
583 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr = NULL;
584 }
585 break;
586 case ExtSocketDescriptor::ESDT_System:
587 close(tdSocket->Socket.SystemSocketID);
588 tdSocket->Socket.SystemSocketID = 0;
589 break;
590 default:
591 SCTPSocketMaster::MasterInstance.unlock();
592 errno_return(-ENXIO);
593 break;
594 }
595
596 // Finally, invalidate socket descriptor
597 tdSocket->Type = ExtSocketDescriptor::ESDT_Invalid;
598
599 SCTPSocketMaster::MasterInstance.unlock();
600 errno_return(0);
601 }
602 errno_return(-EBADF);
603 }
604
605
606 // ###### bind to any address ###############################################
bindToAny(struct ExtSocketDescriptor * tdSocket)607 static int bindToAny(struct ExtSocketDescriptor* tdSocket)
608 {
609 int result = 0;
610 if((tdSocket->Type == ExtSocketDescriptor::ESDT_SCTP) &&
611 (tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) &&
612 (tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getID() <= 0)) {
613 InternetAddress anyAddress;
614 anyAddress.reset();
615
616 SocketAddress* addressArray[2];
617 addressArray[0] = (SocketAddress*)&anyAddress;
618 addressArray[1] = NULL;
619
620 #ifdef RANDOM_PORTSELECTION
621 card16 port;
622 for(cardinal i = 0;i < 50000;i++) {
623 SCTPSocketMaster::MasterInstance.lock();
624 port = (card16)(16384 + SCTPSocketMaster::Random.random32() % (61000 - 16384));
625 SCTPSocketMaster::MasterInstance.unlock();
626 addressArray[0]->setPort(port),
627 #ifdef PRINT_RANDOM_PORTSELECTION
628 std::cout << "trying " << *(addressArray[0]) << "..." << std::endl;
629 #endif
630 #endif
631
632 result = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->bind(
633 addressArray[0]->getPort(),
634 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_instreams,
635 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams,
636 (const SocketAddress**)&addressArray);
637
638 #ifdef RANDOM_PORTSELECTION
639 if(result >= 0) {
640 break;
641 }
642 }
643 #endif
644
645 }
646 errno_return(result);
647 }
648
649
650 // ###### bind() wrapper ####################################################
ext_bind(int sockfd,struct sockaddr * my_addr,socklen_t addrlen)651 int ext_bind(int sockfd, struct sockaddr* my_addr, socklen_t addrlen)
652 {
653 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
654 if(tdSocket != NULL) {
655 switch(tdSocket->Type) {
656 case ExtSocketDescriptor::ESDT_SCTP:
657 return(sctp_bindx(sockfd,my_addr,1,SCTP_BINDX_ADD_ADDR));
658 break;
659 case ExtSocketDescriptor::ESDT_System:
660 return(bind(tdSocket->Socket.SystemSocketID,(sockaddr*)my_addr,addrlen));
661 break;
662 default:
663 errno_return(-ENXIO);
664 break;
665 }
666 }
667 errno_return(-EBADF);
668 }
669
670
671 // ###### sctp_bindx() wrapper ##############################################
sctp_bindx(int sockfd,struct sockaddr * packedAddrs,int addrcnt,int flags)672 int sctp_bindx(int sockfd,
673 struct sockaddr* packedAddrs,
674 int addrcnt,
675 int flags)
676 {
677 sockaddr_storage addrs[addrcnt];
678 unpack_sockaddr(packedAddrs, addrcnt, (sockaddr_storage*)addrs);
679
680 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
681 if(tdSocket != NULL) {
682 switch(tdSocket->Type) {
683 case ExtSocketDescriptor::ESDT_SCTP: {
684 // ====== Check parameters and descriptor ====================
685 if((addrcnt < 1) || (addrcnt > SCTP_MAX_NUM_ADDRESSES)) {
686 errno_return(-EINVAL);
687 }
688 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr == NULL) {
689 errno_return(-EBADF);
690 }
691
692 // ====== Get addresses ======================================
693 SocketAddress* addressArray[addrcnt + 1];
694 sockaddr_storage* a = addrs;
695 for(int i = 0;i < addrcnt;i++) {
696 addressArray[i] = SocketAddress::createSocketAddress(
697 0,(sockaddr*)a,sizeof(sockaddr_storage));
698 if(addressArray[i] == NULL) {
699 for(int j = 0;j < i;j++) {
700 delete addressArray[j];
701 }
702 errno_return(-ENOMEM);
703 }
704 a = (sockaddr_storage*)((long)a + (long)sizeof(sockaddr_storage));
705 }
706 addressArray[addrcnt] = NULL;
707
708 // ====== Bind socket ========================================
709 int result = -EINVAL;
710 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getID() <= 0) {
711 if(flags == SCTP_BINDX_ADD_ADDR) {
712 result = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->bind(
713 addressArray[0]->getPort(),
714 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_instreams,
715 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams,
716 (const SocketAddress**)&addressArray);
717 }
718 }
719 else {
720 if(flags == SCTP_BINDX_ADD_ADDR) {
721 result = 0;
722 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
723 for(int i = 0;i < addrcnt;i++) {
724 const bool ok = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
725 addAddress(*(addressArray[i]));
726 if(!ok) {
727 result = -EINVAL;
728 break;
729 }
730 }
731 }
732 else {
733 for(int i = 0;i < addrcnt;i++) {
734 const bool ok = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
735 addAddress(0,*(addressArray[i]));
736 if(!ok) {
737 result = -EINVAL;
738 break;
739 }
740 }
741 }
742 }
743 else if(flags == SCTP_BINDX_REM_ADDR) {
744 result = 0;
745 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
746 for(int i = 0;i < addrcnt;i++) {
747 const bool ok = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
748 deleteAddress(*(addressArray[i]));
749 if(!ok) {
750 result = -EINVAL;
751 break;
752 }
753 }
754 }
755 else {
756 for(int i = 0;i < addrcnt;i++) {
757 const bool ok = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
758 deleteAddress(0,*(addressArray[i]));
759 if(!ok) {
760 result = -EINVAL;
761 break;
762 }
763 }
764 }
765 }
766 }
767
768 // ====== Remove addresses ===================================
769 for(int i = 0;i < addrcnt;i++) {
770 delete addressArray[i];
771 }
772 errno_return(result);
773 }
774 break;
775 case ExtSocketDescriptor::ESDT_System:
776 return(bind(tdSocket->Socket.SystemSocketID,(sockaddr*)addrs,sizeof(sockaddr_storage)));
777 break;
778 default:
779 errno_return(-ENXIO);
780 break;
781 }
782 }
783 errno_return(-EBADF);
784 }
785
786
787 // ###### listen() wrapper ####################################################
ext_listen(int sockfd,int backlog)788 int ext_listen(int sockfd, int backlog)
789 {
790 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
791 if(tdSocket != NULL) {
792 switch(tdSocket->Type) {
793 case ExtSocketDescriptor::ESDT_SCTP:
794 bindToAny(tdSocket);
795 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
796 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->listen(backlog);
797 errno_return(0);
798 }
799 errno_return(-EOPNOTSUPP);
800 break;
801 case ExtSocketDescriptor::ESDT_System:
802 return(listen(tdSocket->Socket.SystemSocketID,backlog));
803 break;
804 }
805 errno_return(-ENXIO);
806 }
807 errno_return(-EBADF);
808 }
809
810
811 // ###### accept() wrapper ####################################################
ext_accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen)812 int ext_accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
813 {
814 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
815 if(tdSocket != NULL) {
816 switch(tdSocket->Type) {
817 case ExtSocketDescriptor::ESDT_SCTP:
818 {
819 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
820 SocketAddress** remoteAddressArray = NULL;
821 SCTPAssociation* association =
822 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->accept(
823 &remoteAddressArray,
824 !(tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK));
825 if(association != NULL) {
826 if((remoteAddressArray != NULL) &&
827 (remoteAddressArray[0] != NULL) &&
828 (addr != NULL) && (addrlen != NULL)) {
829 *addrlen = remoteAddressArray[0]->getSystemAddress(
830 addr, *addrlen,
831 tdSocket->Socket.SCTPSocketDesc.Domain);
832 }
833 else {
834 addrlen = 0;
835 }
836
837 ExtSocketDescriptor newExtSocketDescriptor = *tdSocket;
838 newExtSocketDescriptor.Socket.SCTPSocketDesc.ConnectionOriented = true;
839 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPSocketPtr = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr;
840 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr = association;
841 const int newFD = ExtSocketDescriptorMaster::setSocket(newExtSocketDescriptor);
842 SocketAddress::deleteAddressList(remoteAddressArray);
843 if(newFD < 0) {
844 delete newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr;
845 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr = NULL;
846 }
847
848 // New socket may not inherit flags from parent socket!
849 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr->setNotificationFlags(
850 SCTP_RECVDATAIOEVNT
851 );
852
853 errno_return(newFD);
854 }
855 else {
856 errno_return(-EWOULDBLOCK);
857 }
858 }
859 errno_return(-EOPNOTSUPP);
860 }
861 break;
862 case ExtSocketDescriptor::ESDT_System:
863 {
864 ExtSocketDescriptor newExtSocketDescriptor = *tdSocket;
865 newExtSocketDescriptor.Socket.SystemSocketID = accept(tdSocket->Socket.SystemSocketID,addr,addrlen);
866 if(newExtSocketDescriptor.Socket.SystemSocketID >= 0) {
867 int result = ExtSocketDescriptorMaster::setSocket(newExtSocketDescriptor);
868 if(result < 0) {
869 close(newExtSocketDescriptor.Socket.SystemSocketID);
870 }
871 errno_return(result);
872 }
873 errno_return(newExtSocketDescriptor.Socket.SystemSocketID);
874 }
875 break;
876 }
877 errno_return(-ENXIO);
878 }
879 errno_return(-EBADF);
880 }
881
882
883 // ###### getsockname() wrapper #############################################
ext_getsockname(int sockfd,struct sockaddr * name,socklen_t * namelen)884 int ext_getsockname(int sockfd, struct sockaddr* name, socklen_t* namelen)
885 {
886 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
887 if(tdSocket != NULL) {
888 switch(tdSocket->Type) {
889 case ExtSocketDescriptor::ESDT_SCTP:
890 {
891 int result = -ENXIO;
892 SocketAddress** localAddressArray = NULL;
893 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
894 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getLocalAddresses(localAddressArray);
895 }
896 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
897 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getLocalAddresses(localAddressArray);
898 }
899 else {
900 result = -EBADF;
901 }
902
903 if((localAddressArray != NULL) &&
904 (localAddressArray[0] != NULL) &&
905 (name != NULL) && (namelen != NULL)) {
906 result = -ENAMETOOLONG;
907 size_t i = 0;
908 while(localAddressArray[i] != NULL) {
909 if(localAddressArray[i]->getSystemAddress(
910 name,*namelen,
911 tdSocket->Socket.SCTPSocketDesc.Domain)) {
912 result = 0;
913 break;
914 }
915 i++;
916 }
917 }
918
919 SocketAddress::deleteAddressList(localAddressArray);
920 errno_return(result);
921 }
922 break;
923 case ExtSocketDescriptor::ESDT_System:
924 return(getsockname(tdSocket->Socket.SystemSocketID,name,namelen));
925 break;
926 }
927 errno_return(-ENXIO);
928 }
929 errno_return(-EBADF);
930 }
931
932
933 // ###### getpeername() wrapper #############################################
ext_getpeername(int sockfd,struct sockaddr * name,socklen_t * namelen)934 int ext_getpeername(int sockfd, struct sockaddr* name, socklen_t* namelen)
935 {
936 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
937 if(tdSocket != NULL) {
938 switch(tdSocket->Type) {
939 case ExtSocketDescriptor::ESDT_SCTP:
940 {
941 int result = -ENXIO;
942 SocketAddress** remoteAddressArray = NULL;
943 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
944 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getRemoteAddresses(remoteAddressArray);
945 }
946 else {
947 result = -EBADF;
948 }
949
950 if((remoteAddressArray != NULL) &&
951 (remoteAddressArray[0] != NULL) &&
952 (name != NULL) && (namelen != NULL)) {
953 result = -ENAMETOOLONG;
954 size_t i = 0;
955 while(remoteAddressArray[i] != NULL) {
956 if(remoteAddressArray[i]->getSystemAddress(
957 name,*namelen,
958 tdSocket->Socket.SCTPSocketDesc.Domain)) {
959 result = 0;
960 break;
961 }
962 i++;
963 }
964 }
965
966 SocketAddress::deleteAddressList(remoteAddressArray);
967 errno_return(result);
968 }
969 break;
970 case ExtSocketDescriptor::ESDT_System:
971 return(getpeername(tdSocket->Socket.SystemSocketID,name,namelen));
972 break;
973 }
974 errno_return(-ENXIO);
975 }
976 errno_return(-EBADF);
977 }
978
979
980 // ###### fcntl() wrapper ###################################################
ext_fcntl(int sockfd,int cmd,...)981 int ext_fcntl(int sockfd, int cmd, ...)
982 {
983 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
984 if(tdSocket != NULL) {
985 va_list va;
986 unsigned long int arg;
987 va_start (va, cmd);
988 arg = va_arg (va, unsigned long int);
989 va_end (va);
990 switch(tdSocket->Type) {
991 case ExtSocketDescriptor::ESDT_SCTP:
992 switch(cmd) {
993 case F_GETFL:
994 errno_return(tdSocket->Socket.SCTPSocketDesc.Flags);
995 break;
996 case F_SETFL:
997 tdSocket->Socket.SCTPSocketDesc.Flags = arg;
998 errno_return(0);
999 break;
1000 default:
1001 errno_return(-EOPNOTSUPP);
1002 break;
1003 }
1004 break;
1005 case ExtSocketDescriptor::ESDT_System:
1006 return(fcntl(tdSocket->Socket.SystemSocketID,cmd,arg));
1007 break;
1008 }
1009 errno_return(-ENXIO);
1010 }
1011 errno_return(-EBADF);
1012 }
1013
1014
1015 // ###### ioctl() wrapper ###################################################
ext_ioctl(int sockfd,int request,const void * argp)1016 int ext_ioctl(int sockfd, int request, const void* argp)
1017 {
1018 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1019 if(tdSocket != NULL) {
1020 switch(tdSocket->Type) {
1021 case ExtSocketDescriptor::ESDT_SCTP:
1022 errno_return(-EOPNOTSUPP);
1023 break;
1024 case ExtSocketDescriptor::ESDT_System:
1025 return(ioctl(tdSocket->Socket.SystemSocketID,request,argp));
1026 break;
1027 }
1028 errno_return(-ENXIO);
1029 }
1030 errno_return(-EBADF);
1031 }
1032
1033
1034 // ###### Get association status ############################################
getAssocStatus(ExtSocketDescriptor * tdSocket,void * optval,socklen_t * optlen)1035 static int getAssocStatus(ExtSocketDescriptor* tdSocket,
1036 void* optval, socklen_t* optlen)
1037 {
1038 if((*optlen < (int)sizeof(sctp_status)) || (optval == NULL)) {
1039 errno_return(-EINVAL);
1040 }
1041 sctp_status* status = (sctp_status*)optval;
1042 unsigned int assocID = status->sstat_assoc_id;
1043 SCTP_Association_Status parameters;
1044
1045 SCTPSocketMaster::MasterInstance.lock();
1046 int result = getAssocParams(tdSocket,assocID,parameters);
1047 if(result == 0) {
1048 status->sstat_state = parameters.state;
1049 status->sstat_rwnd = parameters.currentReceiverWindowSize;
1050 status->sstat_unackdata = parameters.noOfChunksInRetransmissionQueue;
1051 status->sstat_penddata = parameters.noOfChunksInReceptionQueue;
1052 status->sstat_instrms = parameters.inStreams;
1053 status->sstat_outstrms = parameters.outStreams;
1054 status->sstat_fragmentation_point = 0;
1055 status->sstat_assoc_id = assocID;
1056 result = getPrimaryAddressInfo(tdSocket,assocID,status->sstat_primary);
1057 *optlen = sizeof(sctp_status);
1058 }
1059 SCTPSocketMaster::MasterInstance.unlock();
1060 errno_return(result);
1061 }
1062
1063
1064 // ###### Get RTO info ######################################################
getRTOInfo(ExtSocketDescriptor * tdSocket,void * optval,socklen_t * optlen)1065 static int getRTOInfo(ExtSocketDescriptor* tdSocket,
1066 void* optval, socklen_t* optlen)
1067 {
1068 if((optval == NULL) || ((size_t)*optlen < sizeof(sctp_rtoinfo))) {
1069 errno_return(-EINVAL);
1070 }
1071 sctp_rtoinfo* rtoinfo = (sctp_rtoinfo*)optval;
1072 unsigned int assocID = rtoinfo->srto_assoc_id;
1073 SCTP_Association_Status parameters;
1074
1075 int result = getAssocParams(tdSocket,assocID,parameters);
1076 if(result == 0) {
1077 rtoinfo->srto_initial = parameters.rtoInitial;
1078 rtoinfo->srto_max = parameters.rtoMax;
1079 rtoinfo->srto_min = parameters.rtoMin;
1080 rtoinfo->srto_assoc_id = assocID;
1081 *optlen = sizeof(sctp_rtoinfo);
1082 }
1083 errno_return(result);
1084 }
1085
1086
1087 // ###### Get delayed ack time ##############################################
getDelayedAckTime(ExtSocketDescriptor * tdSocket,void * optval,socklen_t * optlen)1088 static int getDelayedAckTime(ExtSocketDescriptor* tdSocket,
1089 void* optval, socklen_t* optlen)
1090 {
1091 if((optval == NULL) || ((size_t)*optlen < sizeof(sctp_sack_info))) {
1092 errno_return(-EINVAL);
1093 }
1094 sctp_sack_info* sackInfo = (sctp_sack_info*)optval;
1095 unsigned int assocID = sackInfo->sack_assoc_id;
1096
1097 if((assocID == 0) && (tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr)) {
1098 assocID = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID();
1099 }
1100
1101 if(assocID != 0) {
1102 SCTP_Association_Status parameters;
1103 int result = getAssocParams(tdSocket, assocID, parameters);
1104 if(result == 0) {
1105 sackInfo->sack_delay = parameters.delay;
1106 *optlen = sizeof(sctp_sack_info);
1107 }
1108 errno_return(result);
1109 }
1110 else {
1111 SCTP_Instance_Parameters parameters;
1112 if(tdSocket->Type == ExtSocketDescriptor::ESDT_SCTP) {
1113 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr) {
1114 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getAssocDefaults(parameters)) {
1115 sackInfo->sack_delay = parameters.delay;
1116 *optlen = sizeof(sctp_sack_info);
1117 errno_return(0);
1118 }
1119 }
1120 }
1121 else {
1122 errno_return(-ENOTSUP);
1123 }
1124 }
1125 errno_return(-EINVAL);
1126 }
1127
1128
1129 // ###### Get RTO info ######################################################
getAssocInfo(ExtSocketDescriptor * tdSocket,void * optval,socklen_t * optlen)1130 static int getAssocInfo(ExtSocketDescriptor* tdSocket,
1131 void* optval, socklen_t* optlen)
1132 {
1133 if((optval == NULL) || ((size_t)*optlen < sizeof(sctp_assocparams))) {
1134 errno_return(-EINVAL);
1135 }
1136 sctp_assocparams* assocparams = (sctp_assocparams*)optval;
1137 unsigned int assocID = assocparams->sasoc_assoc_id;
1138 SCTP_Association_Status parameters;
1139
1140 int result = getAssocParams(tdSocket,assocID,parameters);
1141 if(result == 0) {
1142 assocparams->sasoc_assoc_id = assocID;
1143 assocparams->sasoc_asocmaxrxt = parameters.assocMaxRetransmits;
1144 #if (SCTPLIB_VERSION == SCTPLIB_1_0_0_PRE19) || (SCTPLIB_VERSION == SCTPLIB_1_0_0)
1145 assocparams->sasoc_number_peer_destinations = parameters.numberOfAddresses;
1146 #elif (SCTPLIB_VERSION == SCTPLIB_1_0_0_PRE20) || (SCTPLIB_VERSION == SCTPLIB_1_3_0)
1147 assocparams->sasoc_number_peer_destinations = parameters.numberOfDestinationPaths;
1148 #else
1149 #error Wrong sctplib version!
1150 #endif
1151 assocparams->sasoc_peer_rwnd = 0;
1152 assocparams->sasoc_local_rwnd = parameters.currentReceiverWindowSize;
1153 assocparams->sasoc_cookie_life = parameters.validCookieLife;
1154 *optlen = sizeof(sctp_assocparams);
1155 }
1156 errno_return(result);
1157 }
1158
1159
1160 // ###### Get address information ###########################################
getPeerAddressInfo(ExtSocketDescriptor * tdSocket,void * optval,socklen_t * optlen)1161 static int getPeerAddressInfo(ExtSocketDescriptor* tdSocket,
1162 void* optval, socklen_t* optlen)
1163 {
1164 if((optval == NULL) || ((size_t)*optlen < sizeof(sctp_paddrinfo))) {
1165 errno_return(-EINVAL);
1166 }
1167 int result;
1168 sctp_paddrinfo* paddrinfo = (sctp_paddrinfo*)optval;
1169 unsigned int assocID = paddrinfo->spinfo_assoc_id;
1170 SCTP_PathStatus parameters;
1171
1172 result = getPathStatus(tdSocket,assocID,
1173 (sockaddr*)&paddrinfo->spinfo_address,
1174 sizeof(paddrinfo->spinfo_address),
1175 parameters);
1176 if(result == 0) {
1177 switch(parameters.state) {
1178 case 1:
1179 paddrinfo->spinfo_state = SCTP_INACTIVE;
1180 break;
1181 default:
1182 paddrinfo->spinfo_state = SCTP_ACTIVE;
1183 break;
1184 }
1185 paddrinfo->spinfo_cwnd = parameters.cwnd;
1186 paddrinfo->spinfo_srtt = parameters.srtt;
1187 paddrinfo->spinfo_rto = parameters.rto;
1188 paddrinfo->spinfo_mtu = parameters.mtu;
1189 paddrinfo->spinfo_assoc_id = assocID;
1190 *optlen = sizeof(sctp_paddrinfo);
1191 }
1192 errno_return(result);
1193 }
1194
1195
1196 // ###### Configure address parameters ######################################
configurePeerAddressParams(ExtSocketDescriptor * tdSocket,void * optval,socklen_t * optlen,const bool readOnly)1197 static int configurePeerAddressParams(ExtSocketDescriptor* tdSocket,
1198 void* optval,
1199 socklen_t* optlen,
1200 const bool readOnly)
1201 {
1202 if((optval == NULL) || ((size_t)*optlen < sizeof(sctp_paddrparams))) {
1203 errno_return(-EINVAL);
1204 }
1205 int result;
1206 sctp_paddrparams* newParams = (sctp_paddrparams*)optval;
1207 unsigned int assocID = newParams->spp_assoc_id;
1208 SCTP_PathStatus parameters;
1209
1210 SCTPSocketMaster::MasterInstance.lock();
1211 result = getPathStatus(tdSocket,
1212 assocID,
1213 (sockaddr*)&newParams->spp_address,
1214 sizeof(newParams->spp_address),
1215 parameters);
1216 if(result == 0) {
1217 if(newParams->spp_hbinterval == 0) {
1218 newParams->spp_hbinterval = parameters.heartbeatIntervall;
1219 }
1220 newParams->spp_pathmaxrxt = 0;
1221 newParams->spp_pathmtu = parameters.mtu;
1222 newParams->spp_sackdelay = 0;
1223 newParams->spp_flags = (newParams->spp_hbinterval > 0) ? SPP_HB_ENABLE : SPP_HB_DISABLE;
1224 *optlen = sizeof(sctp_paddrparams);
1225
1226 if(!readOnly) {
1227 parameters.heartbeatIntervall = newParams->spp_hbinterval;
1228 result = setPathStatus(tdSocket,assocID,
1229 (sockaddr*)&newParams->spp_address,
1230 sizeof(newParams->spp_address),
1231 parameters);
1232 }
1233 }
1234 SCTPSocketMaster::MasterInstance.unlock();
1235
1236 errno_return(result);
1237 }
1238
1239
1240 // ###### getsockopt() wrapper ##############################################
ext_getsockopt(int sockfd,int level,int optname,void * optval,socklen_t * optlen)1241 int ext_getsockopt(int sockfd, int level, int optname, void* optval, socklen_t* optlen)
1242 {
1243 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1244 if(tdSocket != NULL) {
1245 switch(tdSocket->Type) {
1246 case ExtSocketDescriptor::ESDT_SCTP:
1247 {
1248 switch(level) {
1249 #if (SYSTEM == OS_Linux)
1250 // ====== IPv6 ============================================
1251 case SOL_IPV6:
1252 switch(optname) {
1253 case IPV6_FLOWINFO:
1254 errno_return(0);
1255 break;
1256 case IPV6_FLOWINFO_SEND:
1257 errno_return(0);
1258 break;
1259 default:
1260 errno_return(-EOPNOTSUPP);
1261 break;
1262 }
1263 break;
1264
1265 // ====== IPv4 ============================================
1266 case SOL_IP:
1267 switch(optname) {
1268 case IP_TOS:
1269 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
1270 errno_return(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getTrafficClass());
1271 }
1272 errno_return(0);
1273 break;
1274 case IP_RECVTOS:
1275 errno_return(0);
1276 break;
1277 default:
1278 errno_return(-EOPNOTSUPP);
1279 break;
1280 }
1281 break;
1282 #endif
1283
1284 // ====== SCTP ============================================
1285 case IPPROTO_SCTP:
1286 switch(optname) {
1287 case SCTP_PEER_ADDR_PARAMS:
1288 return(configurePeerAddressParams(tdSocket,optval,optlen,true));
1289 break;
1290 case SCTP_STATUS:
1291 return(getAssocStatus(tdSocket,optval,optlen));
1292 break;
1293 case SCTP_INITMSG: {
1294 if((optval == NULL) || ((size_t)*optlen < sizeof(sctp_initmsg))) {
1295 errno_return(-EINVAL);
1296 }
1297 sctp_initmsg* initmsg = (sctp_initmsg*)optval;
1298 *initmsg = tdSocket->Socket.SCTPSocketDesc.InitMsg;
1299 *optlen = sizeof(sctp_initmsg);
1300 errno_return(0);
1301 }
1302 break;
1303 case SCTP_GET_PEER_ADDR_INFO:
1304 return(getPeerAddressInfo(tdSocket,optval,optlen));
1305 break;
1306 case SCTP_RTOINFO:
1307 return(getRTOInfo(tdSocket,optval,optlen));
1308 break;
1309 case SCTP_DELAYED_SACK:
1310 return(getDelayedAckTime(tdSocket,optval,optlen));
1311 break;
1312 case SCTP_NODELAY:
1313 errno_return(0);
1314 break;
1315 case SCTP_ASSOCINFO:
1316 return(getAssocInfo(tdSocket,optval,optlen));
1317 break;
1318 case SCTP_AUTOCLOSE:
1319 if((optval == NULL) || ((size_t)*optlen < sizeof(unsigned int))) {
1320 errno_return(-EINVAL);
1321 }
1322 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1323 *((unsigned int*)optval) =
1324 (unsigned int)(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getAutoClose() /
1325 1000000);
1326 *optlen = sizeof(unsigned int);
1327 errno_return(0);
1328 }
1329 errno_return(-EBADF);
1330 break;
1331 default:
1332 errno_return(-EOPNOTSUPP);
1333 break;
1334 }
1335 break;
1336
1337 // ====== Socket ==========================================
1338 case SOL_SOCKET:
1339 switch(optname) {
1340 case SO_SNDBUF:
1341 if((optval == NULL) || ((size_t)*optlen < sizeof(unsigned int))) {
1342 errno_return(-EINVAL);
1343 }
1344 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
1345 *((int*)optval) = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getSendBuffer();
1346 *optlen = sizeof(unsigned int);
1347 errno_return((*((int*)optval) >= 0) ? 0 : -EIO);
1348 }
1349 errno_return(-EBADF);
1350 break;
1351 case SO_RCVBUF:
1352 if((optval == NULL) || ((size_t)*optlen < sizeof(unsigned int))) {
1353 errno_return(-EINVAL);
1354 }
1355 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
1356 *((int*)optval) = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getReceiveBuffer();
1357 *optlen = sizeof(unsigned int);
1358 errno_return((*((int*)optval) >= 0) ? 0 : -EIO);
1359 }
1360 errno_return(-EBADF);
1361 break;
1362 case SO_LINGER:
1363 if((optval == NULL) || ((size_t)*optlen < sizeof(linger))) {
1364 errno_return(-EINVAL);
1365 }
1366 *((linger*)optval) = tdSocket->Socket.SCTPSocketDesc.Linger;
1367 *optlen = sizeof(linger);
1368 errno_return(0);
1369 break;
1370 default:
1371 errno_return(-EOPNOTSUPP);
1372 break;
1373 }
1374 break;
1375
1376 // ====== Default =========================================
1377 default:
1378 errno_return(-EOPNOTSUPP);
1379 break;
1380 }
1381 }
1382 break;
1383 case ExtSocketDescriptor::ESDT_System:
1384 return(getsockopt(tdSocket->Socket.SystemSocketID,level,optname,optval,optlen));
1385 break;
1386 }
1387 errno_return(-ENXIO);
1388 }
1389 errno_return(-EBADF);
1390 }
1391
1392
1393 // ###### Set events ########################################################
setDefaultSendParams(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1394 static int setDefaultSendParams(ExtSocketDescriptor* tdSocket,
1395 const void* optval, const socklen_t optlen)
1396 {
1397 if((optlen != sizeof(sctp_sndrcvinfo)) || (optval == NULL)) {
1398 errno_return(-EINVAL);
1399 }
1400
1401 sctp_sndrcvinfo* sndrcvinfo = (sctp_sndrcvinfo*)optval;
1402 AssocIODefaults defaults;
1403
1404 defaults.StreamID = sndrcvinfo->sinfo_stream;
1405 defaults.ProtoID = sndrcvinfo->sinfo_ppid;
1406 defaults.TimeToLive = sndrcvinfo->sinfo_timetolive;
1407 defaults.Context = sndrcvinfo->sinfo_context;
1408
1409 bool result = false;
1410 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1411 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setAssocIODefaults(defaults);
1412 result = true;
1413 }
1414 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1415 result = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setAssocIODefaults(sndrcvinfo->sinfo_assoc_id,defaults);
1416 }
1417
1418 if(result == true) {
1419 errno_return(0);
1420 }
1421 errno_return(-EINVAL);
1422 }
1423
1424
1425 // ###### Set events ########################################################
setDefaultStreamTimeouts(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1426 static int setDefaultStreamTimeouts(ExtSocketDescriptor* tdSocket,
1427 const void* optval, const socklen_t optlen)
1428 {
1429 if((optlen != sizeof(sctp_setstrm_timeout)) || (optval == NULL)) {
1430 errno_return(-EINVAL);
1431 }
1432
1433 sctp_setstrm_timeout* timeout = (sctp_setstrm_timeout*)optval;
1434
1435 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1436 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setDefaultStreamTimeouts(
1437 timeout->ssto_timeout,
1438 timeout->ssto_streamid_start,
1439 timeout->ssto_streamid_end);
1440 return(0);
1441 }
1442 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1443 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setDefaultStreamTimeouts(
1444 timeout->ssto_assoc_id,
1445 timeout->ssto_timeout,
1446 timeout->ssto_streamid_start,
1447 timeout->ssto_streamid_end)) {
1448 return(0);
1449 }
1450 }
1451 errno_return(-EINVAL);
1452 }
1453
1454
1455 // ###### Set events ########################################################
setEvents(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1456 static int setEvents(ExtSocketDescriptor* tdSocket,
1457 const void* optval, const socklen_t optlen)
1458 {
1459 if((optlen != sizeof(sctp_event_subscribe)) || (optval == NULL)) {
1460 errno_return(-EINVAL);
1461 }
1462
1463 unsigned int flags = 0;
1464 sctp_event_subscribe* events = (sctp_event_subscribe*)optval;
1465
1466 if(events->sctp_data_io_event) {
1467 flags |= SCTP_RECVDATAIOEVNT;
1468 }
1469 if(events->sctp_association_event) {
1470 flags |= SCTP_RECVASSOCEVNT;
1471 }
1472 if(events->sctp_address_event) {
1473 flags |= SCTP_RECVPADDREVNT;
1474 }
1475 if(events->sctp_send_failure_event) {
1476 flags |= SCTP_RECVSENDFAILEVNT;
1477 }
1478 if(events->sctp_peer_error_event) {
1479 flags |= SCTP_RECVPEERERR;
1480 }
1481 if(events->sctp_shutdown_event) {
1482 flags |= SCTP_RECVSHUTDOWNEVNT;
1483 }
1484 if(events->sctp_partial_delivery_event) {
1485 flags |= SCTP_RECVPDEVNT;
1486 }
1487 if(events->sctp_adaptation_layer_event) {
1488 flags |= SCTP_RECVADAPTATIONINDICATION;
1489 }
1490
1491 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1492 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setNotificationFlags(flags);
1493 errno_return(0);
1494 }
1495 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1496 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setNotificationFlags(flags);
1497 errno_return(0);
1498 }
1499 return(-EBADF);
1500 }
1501
1502
1503 // ###### Set RTO info ######################################################
setRTOInfo(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1504 static int setRTOInfo(ExtSocketDescriptor* tdSocket,
1505 const void* optval, const socklen_t optlen)
1506 {
1507 if((optval == NULL) || ((size_t)optlen < sizeof(sctp_rtoinfo))) {
1508 errno_return(-EINVAL);
1509 }
1510 sctp_rtoinfo* rtoinfo = (sctp_rtoinfo*)optval;
1511 unsigned int assocID = rtoinfo->srto_assoc_id;
1512 SCTP_Association_Status parameters;
1513
1514 SCTPSocketMaster::MasterInstance.lock();
1515 int result = getAssocParams(tdSocket,assocID,parameters);
1516 if(result == 0) {
1517 if(rtoinfo->srto_initial != 0) {
1518 parameters.rtoInitial = rtoinfo->srto_initial;
1519 }
1520 if(rtoinfo->srto_min != 0) {
1521 parameters.rtoMin = rtoinfo->srto_min;
1522 }
1523 if(rtoinfo->srto_max != 0) {
1524 parameters.rtoMax = rtoinfo->srto_max;
1525 }
1526 result = setAssocParams(tdSocket,assocID,parameters);
1527 }
1528 SCTPSocketMaster::MasterInstance.unlock();
1529
1530 errno_return(result);
1531 }
1532
1533
1534 // ###### Set delayed ack time ##############################################
setDelayedAckTime(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1535 static int setDelayedAckTime(ExtSocketDescriptor* tdSocket,
1536 const void* optval,
1537 const socklen_t optlen)
1538 {
1539 if((optval == NULL) || (optlen < sizeof(sctp_sack_info))) {
1540 errno_return(-EINVAL);
1541 }
1542 const sctp_sack_info* sackInfo = (const sctp_sack_info*)optval;
1543 unsigned int assocID = sackInfo->sack_assoc_id;
1544
1545 if((assocID == 0) && (tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr)) {
1546 assocID = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID();
1547 }
1548
1549 if(assocID != 0) {
1550 SCTP_Association_Status parameters;
1551 int result = getAssocParams(tdSocket, assocID, parameters);
1552 if(result == 0) {
1553 parameters.delay = sackInfo->sack_delay;
1554 result = setAssocParams(tdSocket, assocID, parameters);
1555 }
1556 errno_return(result);
1557 }
1558 else {
1559 SCTP_Instance_Parameters parameters;
1560 if(tdSocket->Type == ExtSocketDescriptor::ESDT_SCTP) {
1561 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr) {
1562 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getAssocDefaults(parameters)) {
1563 parameters.delay = sackInfo->sack_delay;
1564 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setAssocDefaults(parameters)) {
1565 errno_return(0);
1566 }
1567 }
1568 }
1569 }
1570 else {
1571 errno_return(-ENOTSUP);
1572 }
1573 }
1574 errno_return(-EINVAL);
1575 }
1576
1577
1578 // ###### Set association info ##############################################
setAssocInfo(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1579 static int setAssocInfo(ExtSocketDescriptor* tdSocket,
1580 const void* optval,
1581 const socklen_t optlen)
1582 {
1583 if((optval == NULL) || ((size_t)optlen < sizeof(sctp_assocparams))) {
1584 errno_return(-EINVAL);
1585 }
1586 sctp_assocparams* assocparams = (sctp_assocparams*)optval;
1587 unsigned int assocID = assocparams->sasoc_assoc_id;
1588 SCTP_Association_Status parameters;
1589
1590 SCTPSocketMaster::MasterInstance.lock();
1591 int result = getAssocParams(tdSocket,assocID,parameters);
1592 if(result == 0) {
1593 parameters.assocMaxRetransmits = assocparams->sasoc_asocmaxrxt;
1594 result = setAssocParams(tdSocket,assocID,parameters);
1595 }
1596 SCTPSocketMaster::MasterInstance.unlock();
1597 errno_return(result);
1598 }
1599
1600
1601 // ###### Set primary address ###############################################
setPrimaryAddr(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1602 static int setPrimaryAddr(ExtSocketDescriptor* tdSocket,
1603 const void* optval, const socklen_t optlen)
1604 {
1605 if((optval == NULL) || ((size_t)optlen < sizeof(sctp_setprim))) {
1606 errno_return(-EINVAL);
1607 }
1608 sctp_setprim* setprim = (sctp_setprim*)optval;
1609 SocketAddress* address = SocketAddress::createSocketAddress(0,
1610 (sockaddr*)&setprim->ssp_addr,
1611 sizeof(sockaddr_storage));
1612 if(address == NULL) {
1613 errno_return(-EINVAL);
1614 }
1615
1616 int result = -EBADF;
1617 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1618 result = (tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
1619 setPrimary(*address) == true) ? 0 : -EIO;
1620 }
1621 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1622 result = (tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
1623 setPrimary(setprim->ssp_assoc_id,*address) == true) ? 0 : -EIO;
1624 }
1625
1626 delete address;
1627 errno_return(result);
1628 }
1629
1630
1631 // ###### Set primary address ###############################################
setPeerPrimaryAddr(ExtSocketDescriptor * tdSocket,const void * optval,const socklen_t optlen)1632 static int setPeerPrimaryAddr(ExtSocketDescriptor* tdSocket,
1633 const void* optval, const socklen_t optlen)
1634 {
1635 if((optval == NULL) || ((size_t)optlen < sizeof(sctp_setpeerprim))) {
1636 errno_return(-EINVAL);
1637 }
1638 sctp_setpeerprim* setpeerprim = (sctp_setpeerprim*)optval;
1639 SocketAddress* address = SocketAddress::createSocketAddress(0,
1640 (sockaddr*)&setpeerprim->sspp_addr,
1641 sizeof(sockaddr_storage));
1642 if(address == NULL) {
1643 errno_return(-EINVAL);
1644 }
1645
1646 int result = -EBADF;
1647 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1648 result = (tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->
1649 setPrimary(*address) == true) ? 0 : -EIO;
1650 }
1651 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1652 result = (tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->
1653 setPrimary(setpeerprim->sspp_assoc_id,*address) == true) ? 0 : -EIO;
1654 }
1655
1656 delete address;
1657 errno_return(result);
1658 }
1659
1660
1661 // ###### Get address parameters ############################################
setInitMsg(SCTPSocket * sctpSocket,struct sctp_initmsg * initmsg)1662 static bool setInitMsg(SCTPSocket* sctpSocket, struct sctp_initmsg* initmsg)
1663 {
1664 SCTP_Instance_Parameters parameters;
1665 bool result = false;
1666
1667 SCTPSocketMaster::MasterInstance.lock();
1668 if(sctpSocket->getAssocDefaults(parameters)) {
1669 parameters.outStreams = initmsg->sinit_num_ostreams;
1670 parameters.inStreams = initmsg->sinit_max_instreams;
1671 if(sctpSocket->setAssocDefaults(parameters)) {
1672 result = true;
1673 }
1674 }
1675 SCTPSocketMaster::MasterInstance.unlock();
1676 return(result);
1677 }
1678
1679
1680 // ###### setsockopt() wrapper ##############################################
ext_setsockopt(int sockfd,int level,int optname,const void * optval,socklen_t optlen)1681 int ext_setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen)
1682 {
1683 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1684 if(tdSocket != NULL) {
1685 switch(tdSocket->Type) {
1686 case ExtSocketDescriptor::ESDT_SCTP:
1687 {
1688 switch(level) {
1689 #if (SYSTEM == OS_Linux)
1690 // ====== IPv6 ============================================
1691 case SOL_IPV6:
1692 switch(optname) {
1693 case IPV6_FLOWINFO:
1694 errno_return(0);
1695 break;
1696 case IPV6_FLOWINFO_SEND:
1697 errno_return(0);
1698 break;
1699 default:
1700 errno_return(-EOPNOTSUPP);
1701 break;
1702 }
1703 break;
1704
1705 // ====== IPv4 ============================================
1706 case SOL_IP:
1707 switch(optname) {
1708 case IP_TOS:
1709 if((optval == NULL) || (optlen < sizeof(int))) {
1710 errno_return(-EINVAL);
1711 }
1712 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1713 errno_return((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setTrafficClass(*((int*)optval)) == true) ? 0 : -EIO);
1714 }
1715 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1716 errno_return((tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setTrafficClass(*((int*)optval)) == true) ? 0 : -EIO);
1717 }
1718 errno_return(-EOPNOTSUPP);
1719 break;
1720 case IP_RECVTOS:
1721 errno_return(0);
1722 break;
1723 default:
1724 errno_return(-EOPNOTSUPP);
1725 break;
1726 }
1727 break;
1728 #endif
1729
1730 // ====== SCTP ============================================
1731 case IPPROTO_SCTP:
1732 switch(optname) {
1733 case SCTP_INITMSG: {
1734 if((optval == NULL) || ((size_t)optlen < sizeof(sctp_initmsg))) {
1735 errno_return(-EINVAL);
1736 }
1737 sctp_initmsg* initmsg = (sctp_initmsg*)optval;
1738 tdSocket->Socket.SCTPSocketDesc.InitMsg = *initmsg;
1739 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr) {
1740 setInitMsg(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr,
1741 initmsg);
1742 }
1743 errno_return(0);
1744 }
1745 break;
1746 case SCTP_PEER_ADDR_PARAMS:
1747 return(configurePeerAddressParams(tdSocket,(void*)optval,&optlen,false));
1748 break;
1749 case SCTP_PRIMARY_ADDR:
1750 return(setPrimaryAddr(tdSocket,optval,optlen));
1751 break;
1752 case SCTP_SET_PEER_PRIMARY_ADDR:
1753 return(setPeerPrimaryAddr(tdSocket,optval,optlen));
1754 break;
1755 case SCTP_RTOINFO:
1756 return(setRTOInfo(tdSocket,optval,optlen));
1757 break;
1758 case SCTP_DELAYED_SACK:
1759 return(setDelayedAckTime(tdSocket,optval,optlen));
1760 break;
1761 case SCTP_NODELAY:
1762 errno_return(0);
1763 break;
1764 case SCTP_ASSOCINFO:
1765 return(setAssocInfo(tdSocket,optval,optlen));
1766 break;
1767 case SCTP_EVENTS:
1768 return(setEvents(tdSocket,optval,optlen));
1769 break;
1770 case SCTP_SET_DEFAULT_SEND_PARAM:
1771 return(setDefaultSendParams(tdSocket,optval,optlen));
1772 break;
1773 case SCTP_SET_STREAM_TIMEOUTS:
1774 return(setDefaultStreamTimeouts(tdSocket,optval,optlen));
1775 break;
1776 case SCTP_AUTOCLOSE:
1777 if((optval == NULL) || ((size_t)optlen < sizeof(unsigned int))) {
1778 errno_return(-EINVAL);
1779 }
1780 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr == NULL) {
1781 errno_return(-EBADF);
1782 }
1783 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setAutoClose(
1784 (card64)1000000 * (card64)*((unsigned int*)optval));
1785 errno_return(0);
1786 break;
1787 }
1788 break;
1789
1790 // ====== Socket ==========================================
1791 case SOL_SOCKET:
1792 switch(optname) {
1793 case SO_SNDBUF:
1794 if((optval == NULL) || ((size_t)optlen < sizeof(unsigned int))) {
1795 errno_return(-EINVAL);
1796 }
1797 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1798 errno_return((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setSendBuffer(*((unsigned int*)optval)) == true) ? 0 : -EIO);
1799 }
1800 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1801 errno_return((tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setSendBuffer(*((unsigned int*)optval)) == true) ? 0 : -EIO);
1802 }
1803 errno_return(-EBADF);
1804 break;
1805 case SO_RCVBUF:
1806 if((optval == NULL) || ((size_t)optlen < sizeof(unsigned int))) {
1807 errno_return(-EINVAL);
1808 }
1809 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
1810 errno_return((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->setReceiveBuffer(*((unsigned int*)optval)) == true) ? 0 : -EIO);
1811 }
1812 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1813 errno_return((tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->setReceiveBuffer(*((unsigned int*)optval)) == true) ? 0 : -EIO);
1814 }
1815 errno_return(-EBADF);
1816 break;
1817 case SO_LINGER:
1818 if((optval == NULL) || ((size_t)optlen < sizeof(linger))) {
1819 errno_return(-EINVAL);
1820 }
1821 if( (((linger*)optval)->l_linger < 0) ||
1822 (((linger*)optval)->l_onoff < 0) ||
1823 (((linger*)optval)->l_onoff > 1) ) {
1824 errno_return(-EINVAL);
1825 }
1826 tdSocket->Socket.SCTPSocketDesc.Linger = *((linger*)optval);
1827 errno_return(0);
1828 break;
1829 default:
1830 errno_return(-EOPNOTSUPP);
1831 break;
1832 }
1833 break;
1834
1835 // ====== Default =========================================
1836 default:
1837 errno_return(-EOPNOTSUPP);
1838 break;
1839 }
1840 }
1841 break;
1842 case ExtSocketDescriptor::ESDT_System:
1843 return(setsockopt(tdSocket->Socket.SystemSocketID,level,optname,optval,optlen));
1844 break;
1845 }
1846 errno_return(-ENXIO);
1847 }
1848 errno_return(-EBADF);
1849 }
1850
1851
1852 // ###### shutdown() wrapper ################################################
ext_shutdown(int sockfd,int how)1853 int ext_shutdown(int sockfd, int how)
1854 {
1855 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1856 if(tdSocket != NULL) {
1857 switch(tdSocket->Type) {
1858 case ExtSocketDescriptor::ESDT_SCTP:
1859 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
1860 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->shutdown();
1861 errno_return(0);
1862 }
1863 errno_return(-EOPNOTSUPP);
1864 break;
1865 case ExtSocketDescriptor::ESDT_System:
1866 return(shutdown(tdSocket->Socket.SystemSocketID, how));
1867 break;
1868 }
1869 errno_return(-ENXIO);
1870 }
1871 errno_return(-EBADF);
1872 }
1873
1874
1875 // ###### connect() wrapper #################################################
ext_connect(int sockfd,const struct sockaddr * serv_addr,socklen_t addrlen)1876 int ext_connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)
1877 {
1878 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1879 if(tdSocket != NULL) {
1880 if(tdSocket->Type == ExtSocketDescriptor::ESDT_SCTP) {
1881 struct sockaddr_storage addressArray[1];
1882 memcpy((char*)&addressArray[0], serv_addr, std::min(sizeof(sockaddr_storage), (size_t)addrlen));
1883 return(ext_connectx(sockfd, (const sockaddr*)&addressArray, 1, NULL));
1884 }
1885 else {
1886 return(connect(tdSocket->Socket.SystemSocketID, serv_addr, addrlen));
1887 }
1888 }
1889 errno_return(-EBADF);
1890 }
1891
1892
1893 // ###### connectx() wrapper ################################################
ext_connectx(int sockfd,const struct sockaddr * packedAddrs,int addrcnt,sctp_assoc_t * id)1894 int ext_connectx(int sockfd,
1895 const struct sockaddr* packedAddrs,
1896 int addrcnt,
1897 sctp_assoc_t* id)
1898 {
1899 unsigned int dummy;
1900 sockaddr_storage addrs[addrcnt];
1901 unpack_sockaddr(packedAddrs, addrcnt, addrs);
1902
1903 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1904 if(tdSocket != NULL) {
1905 switch(tdSocket->Type) {
1906 case ExtSocketDescriptor::ESDT_SCTP:
1907 {
1908 #if (SCTPLIB_VERSION == SCTPLIB_1_0_0_PRE19)
1909 if(addrcnt != 1) {
1910 #ifndef DISABLE_WARNINGS
1911 std::cerr << "ERROR: connectx() with more than one address requires sctplib 1.0.0 or better!" << std::endl;
1912 #endif
1913 errno_return(-EOPNOTSUPP);
1914 }
1915 #endif
1916 if(id == NULL) {
1917 id = &dummy;
1918 }
1919 *id = 0;
1920
1921 bindToAny(tdSocket);
1922 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
1923 const SocketAddress* addressArray[addrcnt + 1];
1924 for(int i = 0;i < addrcnt;i++) {
1925 addressArray[i] = SocketAddress::createSocketAddress(
1926 0, (sockaddr*)&addrs[i], sizeof(sockaddr_storage));
1927 if(addressArray[i] == NULL) {
1928 for(int j = i - 1;j > 0;j--) {
1929 delete addressArray[j];
1930 }
1931 errno_return(-EINVAL);
1932 }
1933 }
1934 addressArray[addrcnt] = NULL;
1935
1936 if(tdSocket->Socket.SCTPSocketDesc.ConnectionOriented) {
1937 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr =
1938 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->associate(
1939 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams,
1940 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_attempts,
1941 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_init_timeo,
1942 (const SocketAddress**)&addressArray,
1943 !(tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK));
1944 for(int i = 0;i < addrcnt;i++) {
1945 delete addressArray[i];
1946 addressArray[i] = NULL;
1947 }
1948 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr == NULL) {
1949 errno_return(-EIO);
1950 }
1951 else if(tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK) {
1952 errno_return(-EINPROGRESS);
1953 }
1954 if(id) {
1955 *id = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID();
1956 }
1957 }
1958 else {
1959 int result = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->sendTo(
1960 NULL, 0,
1961 (tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK) ? MSG_DONTWAIT : 0,
1962 *id, 0x0000, 0x00000000, SCTP_INFINITE_LIFETIME,
1963 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_attempts,
1964 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_init_timeo,
1965 true,
1966 (const SocketAddress**)&addressArray,
1967 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams);
1968 for(int i = 0;i < addrcnt;i++) {
1969 delete addressArray[i];
1970 addressArray[i] = NULL;
1971 }
1972 if(result > 0) {
1973 errno_return(result);
1974 }
1975 else if((result == 0) && (tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK)) {
1976 errno_return(-EINPROGRESS);
1977 }
1978 errno_return(result);
1979 }
1980 errno_return(0);
1981 }
1982 errno_return(-EBADF);
1983 }
1984 break;
1985 case ExtSocketDescriptor::ESDT_System:
1986 errno_return(-EOPNOTSUPP);
1987 break;
1988 }
1989 errno_return(-ENXIO);
1990 }
1991 errno_return(-EBADF);
1992 }
1993
1994
1995 // ###### recv() wrapper ####################################################
ext_recv(int sockfd,void * buf,size_t len,int flags)1996 ssize_t ext_recv(int sockfd, void* buf, size_t len, int flags)
1997 {
1998 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
1999 if(tdSocket != NULL) {
2000 switch(tdSocket->Type) {
2001 case ExtSocketDescriptor::ESDT_SCTP:
2002 {
2003 socklen_t fromlen = 0;
2004 return(ext_recvfrom(sockfd,buf,len,flags,NULL,&fromlen));
2005 }
2006 break;
2007 case ExtSocketDescriptor::ESDT_System:
2008 return(recv(tdSocket->Socket.SystemSocketID,buf,len,flags));
2009 break;
2010 }
2011 errno_return(-ENXIO);
2012 }
2013 errno_return(-EBADF);
2014 }
2015
2016
2017 // ###### recvfrom() wrapper ################################################
ext_recvfrom(int sockfd,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)2018 ssize_t ext_recvfrom(int sockfd, void* buf, size_t len, int flags,
2019 struct sockaddr* from, socklen_t* fromlen)
2020 {
2021 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
2022 if(tdSocket != NULL) {
2023 switch(tdSocket->Type) {
2024 case ExtSocketDescriptor::ESDT_SCTP:
2025 {
2026 struct iovec iov = { (char*)buf, len };
2027 char cbuf[1024];
2028 struct msghdr msg = {
2029 #if (SYSTEM == OS_Darwin)
2030 (char*)from,
2031 #else
2032 from,
2033 #endif
2034 (fromlen != NULL) ? *fromlen : 0,
2035 &iov, 1,
2036 cbuf, sizeof(cbuf),
2037 flags
2038 };
2039 int cc = ext_recvmsg2(sockfd,&msg,flags,0);
2040 if(fromlen != NULL) {
2041 *fromlen = msg.msg_namelen;
2042 }
2043 return(cc);
2044 }
2045 break;
2046 case ExtSocketDescriptor::ESDT_System:
2047 const int result = recvfrom(tdSocket->Socket.SystemSocketID,buf,len,flags,from,fromlen);
2048 return(result);
2049 break;
2050 }
2051 errno_return(-ENXIO);
2052 }
2053 errno_return(-EBADF);
2054 }
2055
2056
2057 // ###### recvmsg() wrapper #################################################
ext_recvmsg_singlebuffer(int sockfd,struct msghdr * msg,int flags,const int receiveNotifications)2058 static int ext_recvmsg_singlebuffer(int sockfd, struct msghdr* msg, int flags,
2059 const int receiveNotifications)
2060 {
2061 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
2062 if(tdSocket != NULL) {
2063 unsigned int assocID = 0;
2064 unsigned short streamID = 0;
2065 unsigned int protoID = 0;
2066 uint16_t ssn = 0;
2067 uint32_t tsn = 0;
2068 unsigned int notificationFlags = 0;
2069 SocketAddress* remoteAddress = NULL;
2070 int result = -EOPNOTSUPP;
2071 switch(tdSocket->Type) {
2072 case ExtSocketDescriptor::ESDT_SCTP:
2073 if((msg == NULL) || (msg->msg_iov == NULL)) {
2074 errno_return(-EINVAL);
2075 }
2076 msg->msg_flags |= flags;
2077 #ifndef NON_RECVMSG_NOTIFICATIONS
2078 if(receiveNotifications) {
2079 msg->msg_flags |= MSG_NOTIFICATION;
2080 }
2081 else {
2082 msg->msg_flags &= ~MSG_NOTIFICATION;
2083 }
2084 #else
2085 msg->msg_flags |= MSG_NOTIFICATION;
2086 #endif
2087 if(tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK) {
2088 msg->msg_flags |= MSG_DONTWAIT;
2089 }
2090 if((tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) && (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented)) {
2091 const size_t oldSize = msg->msg_iov->iov_len;
2092 do {
2093 msg->msg_iov->iov_len = oldSize;
2094 result = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->receive(
2095 (char*)msg->msg_iov->iov_base,
2096 msg->msg_iov->iov_len,
2097 msg->msg_flags,
2098 streamID, protoID,
2099 ssn, tsn);
2100 } while((result == -EAGAIN) && !(msg->msg_flags & MSG_DONTWAIT));
2101 notificationFlags = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getNotificationFlags();
2102 assocID = tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID();
2103 }
2104 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
2105 const size_t oldSize = msg->msg_iov->iov_len;
2106 do {
2107 if(remoteAddress != NULL) {
2108 delete remoteAddress;
2109 remoteAddress = NULL;
2110 }
2111 msg->msg_iov->iov_len = oldSize;
2112 result = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->receiveFrom(
2113 (char*)msg->msg_iov->iov_base,
2114 msg->msg_iov->iov_len,
2115 msg->msg_flags,
2116 assocID, streamID, protoID,
2117 ssn, tsn,
2118 &remoteAddress);
2119 } while((result == -EAGAIN) && !(msg->msg_flags & MSG_DONTWAIT));
2120 notificationFlags = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getNotificationFlags();
2121 }
2122 else {
2123 result = -EBADF;
2124 }
2125
2126 // ====== Set result to length in case of success ============
2127 if(result >= 0) {
2128 result = msg->msg_iov->iov_len;
2129 }
2130 break;
2131 case ExtSocketDescriptor::ESDT_System: {
2132 const int result = recvmsg(tdSocket->Socket.SystemSocketID,msg,flags);
2133 return(result);
2134 }
2135 break;
2136 default:
2137 errno_return(-ENXIO);
2138 break;
2139 }
2140
2141 if(result >= 0) {
2142 if((msg->msg_name != NULL) &&
2143 (remoteAddress != NULL)) {
2144 msg->msg_namelen = remoteAddress->getSystemAddress(
2145 (sockaddr*)msg->msg_name,
2146 (socklen_t)msg->msg_namelen,
2147 tdSocket->Socket.SCTPSocketDesc.Domain);
2148 }
2149 else {
2150 msg->msg_namelen = 0;
2151 }
2152 if((notificationFlags & SCTP_RECVDATAIOEVNT) &&
2153 (msg->msg_control != NULL) &&
2154 (msg->msg_controllen >= (socklen_t)CSpace(sizeof(sctp_sndrcvinfo)))) {
2155 cmsghdr* cmsg = (cmsghdr*)msg->msg_control;
2156 cmsg->cmsg_len = CSpace(sizeof(sctp_sndrcvinfo));
2157 cmsg->cmsg_level = IPPROTO_SCTP;
2158 cmsg->cmsg_type = SCTP_SNDRCV;
2159 sctp_sndrcvinfo* info = (sctp_sndrcvinfo*)((long)cmsg + (long)sizeof(cmsghdr));
2160 info->sinfo_stream = streamID;
2161 info->sinfo_ssn = ssn;
2162 info->sinfo_tsn = tsn;
2163 info->sinfo_flags = flags;
2164 info->sinfo_ppid = protoID;
2165 info->sinfo_timetolive = 0;
2166 info->sinfo_context = 0;
2167 info->sinfo_cumtsn = 0;
2168 info->sinfo_assoc_id = assocID;
2169 msg->msg_controllen = CSpace(sizeof(sctp_sndrcvinfo));
2170 }
2171 else {
2172 msg->msg_control = NULL;
2173 msg->msg_controllen = 0;
2174 }
2175 }
2176 else {
2177 msg->msg_namelen = 0;
2178 msg->msg_name = NULL;
2179 msg->msg_controllen = 0;
2180 msg->msg_control = NULL;
2181 }
2182
2183 if(remoteAddress != NULL) {
2184 delete remoteAddress;
2185 }
2186 errno_return(result);
2187 }
2188 errno_return(-EBADF);
2189 }
2190
2191
2192 // ###### recvmsg() wrapper #################################################
ext_recvmsg2(int sockfd,struct msghdr * msg,int flags,const int receiveNotifications)2193 int ext_recvmsg2(int sockfd, struct msghdr* msg, int flags,
2194 const int receiveNotifications)
2195 {
2196 struct iovec* iov = msg->msg_iov;
2197 const size_t count = msg->msg_iovlen;
2198 int result = 0;
2199 for(unsigned int i = 0;i < count;i++) {
2200 msg->msg_iov = (iovec*)((long)iov + ((long)i * (long)sizeof(iovec)));
2201 msg->msg_iovlen = 1;
2202 const int subresult = ext_recvmsg_singlebuffer(sockfd,msg,flags,receiveNotifications);
2203 if(subresult > 0) {
2204 result += subresult;
2205 }
2206 if((result == 0) && (subresult <= 0)) {
2207 result = subresult;
2208 break;
2209 }
2210 if((subresult < (int)msg->msg_iov->iov_len) && (msg->msg_flags & MSG_EOR)) {
2211 break;
2212 }
2213 }
2214 msg->msg_iov = iov;
2215 msg->msg_iovlen = count;
2216 return(result);
2217 }
2218
2219
2220 // ###### recvmsg() wrapper #################################################
ext_recvmsg(int sockfd,struct msghdr * msg,int flags)2221 ssize_t ext_recvmsg(int sockfd, struct msghdr* msg, int flags)
2222 {
2223 return(ext_recvmsg2(sockfd,msg,flags,1));
2224 }
2225
2226
2227 // ###### send() wrapper ####################################################
ext_send(int sockfd,const void * msg,size_t len,int flags)2228 ssize_t ext_send(int sockfd, const void* msg, size_t len, int flags)
2229 {
2230 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
2231 if(tdSocket != NULL) {
2232 switch(tdSocket->Type) {
2233 case ExtSocketDescriptor::ESDT_SCTP:
2234 return(ext_sendto(sockfd,msg,len,flags,NULL,0));
2235 break;
2236 case ExtSocketDescriptor::ESDT_System:
2237 return(send(tdSocket->Socket.SystemSocketID,msg,len,flags));
2238 break;
2239 }
2240 errno_return(-ENXIO);
2241 }
2242 errno_return(-EBADF);
2243 }
2244
2245
2246 // ###### sendto() wrapper ####################################################
ext_sendto(int sockfd,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)2247 ssize_t ext_sendto(int sockfd, const void* buf, size_t len, int flags,
2248 const struct sockaddr* to, socklen_t tolen)
2249 {
2250 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
2251 if(tdSocket != NULL) {
2252 switch(tdSocket->Type) {
2253 case ExtSocketDescriptor::ESDT_SCTP:
2254 {
2255 struct iovec iov = { (char*)buf, len };
2256 struct msghdr msg = {
2257 #if (SYSTEM == OS_Darwin)
2258 (char*)to,
2259 #else
2260 (void*)to,
2261 #endif
2262 tolen,
2263 &iov, 1,
2264 NULL, 0,
2265 flags
2266 };
2267 return(ext_sendmsg(sockfd,&msg,flags));
2268 }
2269 break;
2270 case ExtSocketDescriptor::ESDT_System:
2271 return(sendto(tdSocket->Socket.SystemSocketID,buf,len,flags,to,tolen));
2272 break;
2273 }
2274 errno_return(-ENXIO);
2275 }
2276 errno_return(-EBADF);
2277 }
2278
2279
2280 // ###### sendmsg() wrapper #################################################
ext_sendmsg_singlebuffer(int sockfd,const struct msghdr * msg,int flags)2281 static int ext_sendmsg_singlebuffer(int sockfd, const struct msghdr* msg, int flags)
2282 {
2283 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
2284 if(tdSocket != NULL) {
2285 switch(tdSocket->Type) {
2286 case ExtSocketDescriptor::ESDT_SCTP:
2287 {
2288 if(msg == NULL) {
2289 return(-EINVAL);
2290 }
2291 bindToAny(tdSocket);
2292 bool useDefaults = true;
2293 sctp_sndrcvinfo* info = NULL;
2294 for(const cmsghdr* cmsg = CFirstHeader(msg);
2295 cmsg != NULL;
2296 cmsg = CNextHeader(msg,cmsg)) {
2297 if(cmsg->cmsg_level == IPPROTO_SCTP) {
2298 if(cmsg->cmsg_type == SCTP_SNDRCV) {
2299 if(cmsg->cmsg_len >= (socklen_t)sizeof(sctp_sndrcvinfo)) {
2300 info = (sctp_sndrcvinfo*)CData(cmsg);
2301 useDefaults = false;
2302 }
2303 else {
2304 errno_return(-EINVAL);
2305 }
2306 }
2307 else if(cmsg->cmsg_type == SCTP_INIT) {
2308 const sctp_initmsg* initmsg = (sctp_initmsg*)CData(cmsg);
2309 tdSocket->Socket.SCTPSocketDesc.InitMsg = *initmsg;
2310 if((tdSocket->Socket.SCTPSocketDesc.ConnectionOriented) && (msg->msg_name != NULL)) {
2311 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
2312 errno_return(-EBUSY);
2313 }
2314 const SocketAddress* addressArray[2];
2315 addressArray[0] = SocketAddress::createSocketAddress(
2316 0, (sockaddr*)msg->msg_name, msg->msg_namelen);
2317 addressArray[1] = NULL;
2318 if(addressArray[0] != NULL) {
2319 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr =
2320 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->associate(
2321 initmsg->sinit_num_ostreams,
2322 initmsg->sinit_max_attempts,
2323 initmsg->sinit_max_init_timeo,
2324 (const SocketAddress**)&addressArray,
2325 !(tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK));
2326 delete addressArray[0];
2327 addressArray[0] = NULL;
2328 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr == NULL) {
2329 errno_return(-ENOTCONN);
2330 }
2331 }
2332 else {
2333 errno_return(-EADDRNOTAVAIL);
2334 }
2335 }
2336 }
2337 }
2338 }
2339
2340 flags |= msg->msg_flags;
2341 if(info != NULL) {
2342 flags |= info->sinfo_flags;
2343 }
2344 if(tdSocket->Socket.SCTPSocketDesc.Flags & O_NONBLOCK) {
2345 flags |= MSG_DONTWAIT;
2346 }
2347 if(msg->msg_name != NULL) {
2348 int result = -EBADF;
2349 const SocketAddress* destinationAddressList[SCTP_MAX_NUM_ADDRESSES + 1];
2350 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
2351 if(!(flags & MSG_MULTIADDRS)) {
2352 destinationAddressList[0] = SocketAddress::createSocketAddress(
2353 0, (sockaddr*)msg->msg_name, msg->msg_namelen);
2354 destinationAddressList[1] = NULL;
2355 }
2356 else {
2357 sockaddr* sa = (sockaddr*)msg->msg_name;
2358 size_t i;
2359 for(i = 0;i < (size_t)msg->msg_namelen;i++) {
2360 destinationAddressList[i] = SocketAddress::createSocketAddress(
2361 0, sa, sizeof(sockaddr_storage));
2362 if(destinationAddressList[i] == NULL) {
2363 errno_return(-EINVAL);
2364 }
2365 // std::cout << "#" << i << ": " << *(destinationAddressList[i]) << std::endl;
2366 switch(sa->sa_family) {
2367 case AF_INET:
2368 sa = (sockaddr*)((long)sa + sizeof(sockaddr_in));
2369 break;
2370 case AF_INET6:
2371 sa = (sockaddr*)((long)sa + sizeof(sockaddr_in6));
2372 break;
2373 default:
2374 errno_return(-EINVAL);
2375 break;
2376 }
2377 }
2378 destinationAddressList[i++] = NULL;
2379 }
2380 unsigned int idZero = 0;
2381 result = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->sendTo(
2382 (char*)msg->msg_iov->iov_base,
2383 msg->msg_iov->iov_len,
2384 flags,
2385 (info != NULL) ? info->sinfo_assoc_id : idZero,
2386 (info != NULL) ? info->sinfo_stream : 0x0000,
2387 (info != NULL) ? info->sinfo_ppid : 0x00000000,
2388 ((info != NULL) && (info->sinfo_flags & MSG_PR_SCTP_TTL)) ? info->sinfo_timetolive : SCTP_INFINITE_LIFETIME,
2389 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_attempts,
2390 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_init_timeo,
2391 useDefaults,
2392 (const SocketAddress**)&destinationAddressList,
2393 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams);
2394 for(size_t i = 0;i < SCTP_MAX_NUM_ADDRESSES;i++) {
2395 if(destinationAddressList[i] != NULL) {
2396 delete destinationAddressList[i];
2397 destinationAddressList[i] = NULL;
2398 }
2399 else {
2400 break;
2401 }
2402 }
2403 }
2404 errno_return(result);
2405 }
2406 else {
2407 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
2408 errno_return(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->send(
2409 (char*)msg->msg_iov->iov_base,
2410 msg->msg_iov->iov_len,
2411 flags,
2412 (info != NULL) ? info->sinfo_stream : 0x0000,
2413 (info != NULL) ? info->sinfo_ppid : 0x0000000,
2414 ((info != NULL) && (info->sinfo_flags & MSG_PR_SCTP_TTL)) ? info->sinfo_timetolive : SCTP_INFINITE_LIFETIME,
2415 useDefaults));
2416 }
2417 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
2418 unsigned int idZero = 0;
2419 errno_return(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->sendTo(
2420 (char*)msg->msg_iov->iov_base,
2421 msg->msg_iov->iov_len,
2422 flags,
2423 (info != NULL) ? info->sinfo_assoc_id : idZero,
2424 (info != NULL) ? info->sinfo_stream : 0x0000,
2425 (info != NULL) ? info->sinfo_ppid : 0x00000000,
2426 ((info != NULL) && (info->sinfo_flags & MSG_PR_SCTP_TTL)) ? info->sinfo_timetolive : SCTP_INFINITE_LIFETIME,
2427 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_attempts,
2428 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_max_init_timeo,
2429 useDefaults,
2430 NULL,
2431 tdSocket->Socket.SCTPSocketDesc.InitMsg.sinit_num_ostreams));
2432 }
2433 errno_return(-EBADF);
2434 }
2435 errno_return(0);
2436 }
2437 break;
2438 case ExtSocketDescriptor::ESDT_System:
2439 return(sendmsg(tdSocket->Socket.SystemSocketID,msg,flags));
2440 break;
2441 }
2442 errno_return(-ENXIO);
2443 }
2444 errno_return(-EBADF);
2445 }
2446
2447
2448 // ###### sendmsg() wrapper #################################################
ext_sendmsg(int sockfd,const struct msghdr * msg,int flags)2449 ssize_t ext_sendmsg(int sockfd, const struct msghdr* msg, int flags)
2450 {
2451 struct iovec* iov = msg->msg_iov;
2452 const size_t count = msg->msg_iovlen;
2453
2454 if(count > 1) {
2455 size_t required = 0;
2456 for(unsigned int i = 0;i < count;i++) {
2457 const iovec* subvec = (iovec*)((long)iov + ((long)i * (long)sizeof(iovec)));
2458 required += subvec->iov_len;
2459 }
2460
2461 char* buffer = new char[required];
2462 if(buffer == NULL) {
2463 return(-ENOMEM);
2464 }
2465 unsigned int j = 0;
2466 for(unsigned int i = 0;i < count;i++) {
2467 const iovec* subvec = (iovec*)((long)iov + ((long)i * (long)sizeof(iovec)));
2468 const char* base = (char*)subvec->iov_base;
2469 for(unsigned int k = 0;k < subvec->iov_len;k++) {
2470 buffer[j++] = base[k];
2471 }
2472 }
2473
2474 iovec newvec;
2475 newvec.iov_len = required;
2476 newvec.iov_base = buffer;
2477
2478 msghdr newmsg;
2479 newmsg.msg_control = msg->msg_control;
2480 newmsg.msg_controllen = msg->msg_controllen;
2481 newmsg.msg_name = msg->msg_name;
2482 newmsg.msg_namelen = msg->msg_namelen;
2483 newmsg.msg_iov = &newvec;
2484 newmsg.msg_iovlen = 1;
2485 newmsg.msg_flags = msg->msg_flags;
2486 const int result = ext_sendmsg_singlebuffer(sockfd,&newmsg,flags);
2487
2488 delete [] buffer;
2489 return(result);
2490 }
2491 else {
2492 return(ext_sendmsg_singlebuffer(sockfd,msg,flags));
2493 }
2494 }
2495
2496
2497 // ###### read() wrapper ####################################################
ext_read(int fd,void * buf,size_t count)2498 ssize_t ext_read(int fd, void* buf, size_t count)
2499 {
2500 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(fd);
2501 if(tdSocket != NULL) {
2502 if(tdSocket->Type == ExtSocketDescriptor::ESDT_System) {
2503 return(read(tdSocket->Socket.SystemSocketID,buf,count));
2504 }
2505 else {
2506 return(ext_recv(fd,buf,count,0));
2507 }
2508 }
2509 errno_return(-EBADF);
2510 }
2511
2512
2513 // ###### write() wrapper ####################################################
ext_write(int fd,const void * buf,size_t count)2514 ssize_t ext_write(int fd, const void* buf, size_t count)
2515 {
2516 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(fd);
2517 if(tdSocket != NULL) {
2518 if(tdSocket->Type == ExtSocketDescriptor::ESDT_System) {
2519 return(write(tdSocket->Socket.SystemSocketID,buf,count));
2520 }
2521 else {
2522 return(ext_send(fd,buf,count,0));
2523 }
2524 }
2525 errno_return(-EBADF);
2526 }
2527
2528
2529 // Internal structure for ext_select().
2530 struct SelectData
2531 {
2532 cardinal Conditions;
2533 int ConditionFD[FD_SETSIZE];
2534 cardinal ConditionType[FD_SETSIZE];
2535 Condition* ConditionArray[FD_SETSIZE];
2536 Condition* ParentConditionArray[FD_SETSIZE];
2537 Condition GlobalCondition;
2538 Condition ReadCondition;
2539 Condition WriteCondition;
2540 Condition ExceptCondition;
2541 cardinal UserCallbacks;
2542 int UserCallbackFD[FD_SETSIZE];
2543 SCTPSocketMaster::UserSocketNotification* UserNotification[FD_SETSIZE];
2544 };
2545
2546
2547 // ###### Add file descriptor to SelectData structure #######################
collectSCTP_FDs(SelectData & selectData,const int fd,struct ExtSocketDescriptor * tdSocket,const UpdateConditionType type,Condition & condition)2548 static int collectSCTP_FDs(SelectData& selectData,
2549 const int fd,
2550 struct ExtSocketDescriptor* tdSocket,
2551 const UpdateConditionType type,
2552 Condition& condition)
2553 {
2554 selectData.UserCallbackFD[selectData.UserCallbacks] = fd;
2555 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
2556 selectData.ConditionArray[selectData.Conditions] =
2557 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getUpdateCondition(type);
2558
2559 #ifdef PRINT_SELECT
2560 if(selectData.ConditionArray[selectData.Conditions]->peekFired()) {
2561 std::cout << "collectSCTP_FDs: condition already fired" << std::endl;
2562 }
2563 #endif
2564
2565 selectData.ParentConditionArray[selectData.Conditions] = &condition;
2566 selectData.ConditionArray[selectData.Conditions]->addParent(selectData.ParentConditionArray[selectData.Conditions]);
2567 selectData.ConditionFD[selectData.Conditions] = fd;
2568 selectData.ConditionType[selectData.Conditions] = type;
2569 selectData.Conditions++;
2570 return(0);
2571 }
2572 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
2573 selectData.ConditionArray[selectData.Conditions] =
2574 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getUpdateCondition(type);
2575 if((type == UCT_Write) &&
2576 (tdSocket->Socket.SCTPSocketDesc.ConnectionOriented == false)) {
2577 selectData.ConditionArray[selectData.Conditions]->signal();
2578 #ifdef PRINT_SELECT
2579 std::cout << "collectSCTP_FDs: UDP-like sockets are always writable" << std::endl;
2580 #endif
2581 }
2582
2583 #ifdef PRINT_SELECT
2584 if(selectData.ConditionArray[selectData.Conditions]->peekFired()) {
2585 std::cout << "collectSCTP_FDs: condition already fired" << std::endl;
2586 }
2587 #endif
2588
2589 selectData.ParentConditionArray[selectData.Conditions] = &condition;
2590 selectData.ConditionArray[selectData.Conditions]->addParent(selectData.ParentConditionArray[selectData.Conditions]);
2591 selectData.ConditionFD[selectData.Conditions] = fd;
2592 selectData.ConditionType[selectData.Conditions] = type;
2593 selectData.Conditions++;
2594 return(0);
2595 }
2596 else {
2597 return(-EBADF);
2598 }
2599 }
2600
2601
2602 // ###### Add file descriptor to SelectData structure #######################
collectFDs(SelectData & selectData,const int fd,const short int eventMask)2603 static int collectFDs(SelectData& selectData,
2604 const int fd,
2605 const short int eventMask)
2606 {
2607 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(fd);
2608 if(tdSocket != NULL) {
2609 if(tdSocket->Type == ExtSocketDescriptor::ESDT_Invalid) {
2610 #ifndef DISABLE_WARNINGS
2611 std::cerr << "WARNING: Invalid socket FD given for collectFDs(): " << fd << "!" << std::endl;
2612 #endif
2613 }
2614 else if(tdSocket->Type == ExtSocketDescriptor::ESDT_System) {
2615 #ifdef PRINT_SELECT
2616 char str[32];
2617 snprintf((char*)&str,sizeof(str),"$%04x",eventMask);
2618 std::cout << "select(" << getpid() << "): adding FD " << tdSocket->Socket.SystemSocketID
2619 << " (" << fd << ") with mask " << str << std::endl;
2620 #endif
2621 selectData.UserCallbackFD[selectData.UserCallbacks] = fd;
2622 selectData.UserNotification[selectData.UserCallbacks] = new SCTPSocketMaster::UserSocketNotification;
2623 if(selectData.UserNotification[selectData.UserCallbacks] != NULL) {
2624 selectData.UserNotification[selectData.UserCallbacks]->FileDescriptor = tdSocket->Socket.SystemSocketID;
2625 selectData.UserNotification[selectData.UserCallbacks]->EventMask = eventMask;
2626 #ifdef PRINT_SELECT
2627 std::cout << "select(" << getpid() << "): registering user callback for socket "
2628 << tdSocket->Socket.SystemSocketID << "..." << std::endl;
2629 #endif
2630 if(eventMask & POLLIN) {
2631 selectData.UserNotification[selectData.UserCallbacks]->UpdateCondition.addParent(&selectData.ReadCondition);
2632 }
2633 if(eventMask & POLLOUT) {
2634 selectData.UserNotification[selectData.UserCallbacks]->UpdateCondition.addParent(&selectData.WriteCondition);
2635 }
2636 if(eventMask & POLLERR) {
2637 selectData.UserNotification[selectData.UserCallbacks]->UpdateCondition.addParent(&selectData.ExceptCondition);
2638 }
2639 SCTPSocketMaster::MasterInstance.addUserSocketNotification(selectData.UserNotification[selectData.UserCallbacks]);
2640
2641 selectData.UserCallbacks++;
2642 return(0);
2643 }
2644 }
2645 else {
2646 int result = 0;
2647 if(eventMask & POLLIN) {
2648 #ifdef PRINT_SELECT
2649 std::cout << "select(" << getpid() << "): adding FD " << fd << " for read" << std::endl;
2650 #endif
2651 result = collectSCTP_FDs(selectData,fd,tdSocket,UCT_Read,selectData.ReadCondition);
2652 }
2653 if(eventMask & POLLOUT) {
2654 #ifdef PRINT_SELECT
2655 std::cout << "select(" << getpid() << "): adding FD " << fd << " for write" << std::endl;
2656 #endif
2657 result = collectSCTP_FDs(selectData,fd,tdSocket,UCT_Write,selectData.WriteCondition);
2658 }
2659 if(eventMask & POLLERR) {
2660 #ifdef PRINT_SELECT
2661 std::cout << "select(" << getpid() << "): adding FD " << fd << " for except" << std::endl;
2662 #endif
2663 result = collectSCTP_FDs(selectData,fd,tdSocket,UCT_Except,selectData.ExceptCondition);
2664 }
2665 errno_return(result);
2666 }
2667 }
2668 errno_return(-EBADF);
2669 }
2670
2671
2672 // ###### select() wrapper ##################################################
select_wrapper(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)2673 static int select_wrapper(int n,
2674 fd_set* readfds,
2675 fd_set* writefds,
2676 fd_set* exceptfds,
2677 struct timeval* timeout)
2678 {
2679 bool fakeUDPWrite = false;
2680 fd_set r;
2681 fd_set w;
2682 fd_set e;
2683 FD_ZERO(&r);
2684 FD_ZERO(&w);
2685 FD_ZERO(&e);
2686 int maxFD = 0;
2687 int reverseMapping[ExtSocketDescriptorMaster::MaxSockets];
2688 for(unsigned int i = 0;i < std::min((const unsigned int)n,(const unsigned int)FD_SETSIZE);i++) {
2689 if(SAFE_FD_ISSET(i,readfds) || SAFE_FD_ISSET(i,writefds) || SAFE_FD_ISSET(i,exceptfds)) {
2690 ExtSocketDescriptor* socket = ExtSocketDescriptorMaster::getSocket(i);
2691 if(socket != NULL) {
2692 if(socket->Type == ExtSocketDescriptor::ESDT_System) {
2693 const int fd = socket->Socket.SystemSocketID;
2694 maxFD = std::max(maxFD,fd);
2695
2696 if(SAFE_FD_ISSET(i,readfds)) {
2697 FD_SET(fd,&r);
2698 }
2699 if(SAFE_FD_ISSET(i,writefds)) {
2700 FD_SET(fd,&w);
2701 }
2702 if(SAFE_FD_ISSET(i,exceptfds)) {
2703 FD_SET(fd,&e);
2704 }
2705 #ifdef PRINT_SELECT
2706 std::cout << "select(" << getpid() << "): added FD " << fd << " (" << i << ")" << std::endl;
2707 #endif
2708 reverseMapping[fd] = i;
2709 }
2710 else if((socket->Type == ExtSocketDescriptor::ESDT_SCTP) &&
2711 (socket->Socket.SCTPSocketDesc.ConnectionOriented == false)) {
2712 #ifdef PRINT_SELECT
2713 std::cout << "select(" << getpid() << "): added FD " << i << " - Unbound UDP-like SCTP socket" << std::endl;
2714 #endif
2715 fakeUDPWrite = true;
2716 }
2717 else {
2718 #ifndef DISABLE_WARNINGS
2719 std::cerr << "WARNING: select_wrapper() - Bad FD " << i << "!" << std::endl;
2720 #endif
2721 }
2722 }
2723 }
2724 }
2725
2726 #ifdef PRINT_SELECT
2727 std::cout << "select..." << std::endl;
2728 #endif
2729 int result;
2730 if(!fakeUDPWrite) {
2731 result = select(maxFD + 1,&r,&w,&e,timeout);
2732 }
2733 else {
2734 struct timeval mytimeout;
2735 mytimeout.tv_sec = 0;
2736 mytimeout.tv_usec = 0;
2737 result = select(maxFD + 1,&r,&w,&e,&mytimeout);
2738 }
2739 #ifdef PRINT_SELECT
2740 std::cout << "select result " << result << std::endl;
2741 #endif
2742
2743 if(result >= 0) {
2744 SAFE_FD_ZERO(readfds);
2745 SAFE_FD_ZERO(exceptfds);
2746 if(!fakeUDPWrite) {
2747 SAFE_FD_ZERO(writefds);
2748 }
2749 else {
2750 for(unsigned int i = 0;i < FD_SETSIZE;i++) {
2751 if(SAFE_FD_ISSET(i,writefds)) {
2752 ExtSocketDescriptor* socket = ExtSocketDescriptorMaster::getSocket(i);
2753 if((socket != NULL) &&
2754 (socket->Type == ExtSocketDescriptor::ESDT_SCTP) &&
2755 (socket->Socket.SCTPSocketDesc.ConnectionOriented == false)) {
2756 #ifdef PRINT_SELECT
2757 std::cout << "select(" << getpid() << "): write for FD " << i
2758 << " (Unbound UDP-like SCTP socket)" << std::endl;
2759 #endif
2760 FD_SET(i,writefds);
2761 result++;
2762 }
2763 else {
2764 FD_CLR(i,writefds);
2765 }
2766 }
2767 }
2768 }
2769 for(int i = 0;i <= maxFD;i++) {
2770 if(SAFE_FD_ISSET(i,&r)) {
2771 #ifdef PRINT_SELECT
2772 std::cout << "select(" << getpid() << "): read for FD " << reverseMapping[i] << std::endl;
2773 #endif
2774 FD_SET(reverseMapping[i],readfds);
2775 }
2776 if(SAFE_FD_ISSET(i,&w)) {
2777 #ifdef PRINT_SELECT
2778 std::cout << "select(" << getpid() << "): write for FD " << reverseMapping[i] << std::endl;
2779 #endif
2780 FD_SET(reverseMapping[i],writefds);
2781 }
2782 if(SAFE_FD_ISSET(i,&e)) {
2783 #ifdef PRINT_SELECT
2784 std::cout << "select(" << getpid() << "): except for FD " << reverseMapping[i] << std::endl;
2785 #endif
2786 FD_SET(reverseMapping[i],exceptfds);
2787 }
2788 }
2789 }
2790
2791 return(result);
2792 }
2793
2794
2795 // ###### ext_select() implementation #######################################
ext_select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)2796 int ext_select(int n,
2797 fd_set* readfds,
2798 fd_set* writefds,
2799 fd_set* exceptfds,
2800 struct timeval* timeout)
2801 {
2802 if(!SCTPSocketMaster::MasterInstance.running()) {
2803 // SCTP is not available -> Use select() wrapper for conversion
2804 // of FDs to system FDs and back.
2805 return(select_wrapper(n,readfds,writefds,exceptfds,timeout));
2806 }
2807
2808 SCTPSocketMaster::MasterInstance.lock();
2809
2810 SelectData selectData;
2811 selectData.Conditions = 0;
2812 selectData.UserCallbacks = 0;
2813 selectData.GlobalCondition.setName("ext_select::GlobalCondition");
2814 selectData.ReadCondition.setName("ext_select::ReadCondition");
2815 selectData.WriteCondition.setName("ext_select::WriteCondition");
2816 selectData.ExceptCondition.setName("ext_select::ExceptCondition");
2817 selectData.ReadCondition.addParent(&selectData.GlobalCondition);
2818 selectData.WriteCondition.addParent(&selectData.GlobalCondition);
2819 selectData.ExceptCondition.addParent(&selectData.GlobalCondition);
2820
2821 int result = 0;
2822 for(int i = 0;i < std::min((const int)n,(const int)FD_SETSIZE);i++) {
2823 short int eventMask = 0;
2824 if(SAFE_FD_ISSET(i,readfds)) {
2825 eventMask |= POLLIN|POLLPRI;
2826 }
2827 if(SAFE_FD_ISSET(i,writefds)) {
2828 eventMask |= POLLOUT;
2829 }
2830 if(SAFE_FD_ISSET(i,exceptfds)) {
2831 eventMask |= POLLERR;
2832 }
2833 if(eventMask) {
2834 result = collectFDs(selectData,i,eventMask);
2835 if(result != 0) {
2836 break;
2837 }
2838 }
2839 }
2840
2841 if(result == 0) {
2842 SCTPSocketMaster::MasterInstance.unlock();
2843 if((selectData.Conditions > 0) || (selectData.UserCallbacks > 0)) {
2844 #ifdef PRINT_SELECT
2845 std::cout << "select(" << getpid() << "): waiting..." << std::endl;
2846 #endif
2847
2848 if(timeout != NULL) {
2849 const card64 delay = ((card64)timeout->tv_sec * (card64)1000000) +
2850 (card64)timeout->tv_usec;
2851 selectData.GlobalCondition.timedWait(delay);
2852 }
2853 else {
2854 selectData.GlobalCondition.wait();
2855 }
2856
2857 #ifdef PRINT_SELECT
2858 std::cout << "select(" << getpid() << "): wake-up" << std::endl;
2859 #endif
2860 }
2861 else {
2862 result = select(0, NULL, NULL, NULL,timeout);
2863 }
2864
2865 SCTPSocketMaster::MasterInstance.lock();
2866 }
2867
2868 if(readfds != NULL) {
2869 for(cardinal i = 0;i < selectData.Conditions;i++) {
2870 FD_CLR(selectData.ConditionFD[i],readfds);
2871 }
2872 }
2873 if(writefds != NULL) {
2874 for(cardinal i = 0;i < selectData.Conditions;i++) {
2875 FD_CLR(selectData.ConditionFD[i],writefds);
2876 }
2877 }
2878 if(exceptfds != NULL) {
2879 for(cardinal i = 0;i < selectData.Conditions;i++) {
2880 FD_CLR(selectData.ConditionFD[i],exceptfds);
2881 }
2882 }
2883
2884 int changes = 0;
2885 for(cardinal i = 0;i < selectData.Conditions;i++) {
2886 if(selectData.ConditionArray[i]->fired()) {
2887 changes++;
2888 switch(selectData.ConditionType[i]) {
2889 case UCT_Read:
2890 if(readfds != NULL) {
2891 #ifdef PRINT_SELECT
2892 std::cout << "select(" << getpid() << "): got read for FD " << selectData.ConditionFD[i] << "." << std::endl;
2893 #endif
2894 FD_SET(selectData.ConditionFD[i],readfds);
2895 }
2896 break;
2897 case UCT_Write:
2898 if(writefds != NULL) {
2899 #ifdef PRINT_SELECT
2900 std::cout << "select(" << getpid() << "): got write for FD " << selectData.ConditionFD[i] << "." << std::endl;
2901 #endif
2902 FD_SET(selectData.ConditionFD[i],writefds);
2903 }
2904 break;
2905 case UCT_Except:
2906 if(exceptfds != NULL) {
2907 #ifdef PRINT_SELECT
2908 std::cout << "select(" << getpid() << "): got except for FD " << selectData.ConditionFD[i] << "." << std::endl;
2909 #endif
2910 FD_SET(selectData.ConditionFD[i],exceptfds);
2911 }
2912 break;
2913 }
2914
2915 }
2916 selectData.ConditionArray[i]->removeParent(selectData.ParentConditionArray[i]);
2917 }
2918 if(readfds != NULL) {
2919 for(cardinal i = 0;i < selectData.UserCallbacks;i++) {
2920 FD_CLR(selectData.UserCallbackFD[i],readfds);
2921 }
2922 }
2923 if(writefds != NULL) {
2924 for(cardinal i = 0;i < selectData.UserCallbacks;i++) {
2925 FD_CLR(selectData.UserCallbackFD[i],writefds);
2926 }
2927 }
2928 if(exceptfds != NULL) {
2929 for(cardinal i = 0;i < selectData.UserCallbacks;i++) {
2930 FD_CLR(selectData.UserCallbackFD[i],exceptfds);
2931 }
2932 }
2933 for(cardinal i = 0;i < selectData.UserCallbacks;i++) {
2934 SCTPSocketMaster::MasterInstance.deleteUserSocketNotification(selectData.UserNotification[i]);
2935
2936 if(selectData.UserNotification[i]->Events) {
2937 #ifdef PRINT_SELECT
2938 char str[32];
2939 snprintf((char*)&str,sizeof(str),"$%04x",selectData.UserNotification[i]->Events);
2940 std::cout << "select(" << getpid() << "): events " << str << " for FD " << selectData.UserNotification[i]->FileDescriptor << " ("
2941 << selectData.UserCallbackFD[i] << ")" << std::endl;
2942 #endif
2943 }
2944
2945 bool changed = false;
2946 if((readfds != NULL) && (selectData.UserNotification[i]->Events & (POLLIN|POLLPRI))) {
2947 #ifdef PRINT_SELECT
2948 std::cout << "select(" << getpid() << "): got read for FD " << selectData.UserNotification[i]->FileDescriptor << " ("
2949 << selectData.UserCallbackFD[i] << ")" << std::endl;
2950 #endif
2951 FD_SET(selectData.UserCallbackFD[i],readfds);
2952 changed = true;
2953 }
2954 if((writefds != NULL) && (selectData.UserNotification[i]->Events & POLLOUT)) {
2955 #ifdef PRINT_SELECT
2956 std::cout << "select(" << getpid() << "): got write for FD " << selectData.UserNotification[i]->FileDescriptor << " ("
2957 << selectData.UserCallbackFD[i] << ")" << std::endl;
2958 #endif
2959 FD_SET(selectData.UserCallbackFD[i],writefds);
2960 changed = true;
2961 }
2962 if((exceptfds != NULL) && (selectData.UserNotification[i]->Events & (~(POLLIN|POLLPRI|POLLOUT)))) {
2963 #ifdef PRINT_SELECT
2964 std::cout << "select(" << getpid() << "): got except for FD " << selectData.UserNotification[i]->FileDescriptor << " ("
2965 << selectData.UserCallbackFD[i] << ")" << std::endl;
2966 #endif
2967 FD_SET(selectData.UserCallbackFD[i],exceptfds);
2968 changed = true;
2969 }
2970 if(changed) {
2971 changes++;
2972 }
2973
2974 delete selectData.UserNotification[i];
2975 }
2976
2977 SCTPSocketMaster::MasterInstance.unlock();
2978
2979 errno_return((result < 0) ? result : changes);
2980 }
2981
2982
2983 // ###### An implementation of poll(), based on ext_select() ################
ext_poll(struct pollfd * fdlist,long unsigned int count,int time)2984 int ext_poll(struct pollfd* fdlist, long unsigned int count, int time)
2985 {
2986 // ====== Prepare timeout setting ========================================
2987 timeval timeout;
2988 timeval* to;
2989 if(time < 0)
2990 to = NULL;
2991 else {
2992 to = &timeout;
2993 timeout.tv_sec = time / 1000;
2994 timeout.tv_usec = (time % 1000) * 1000;
2995 }
2996
2997 // ====== Prepare FD settings ============================================
2998 int fdcount = 0;
2999 int n = 0;
3000 fd_set readfdset;
3001 fd_set writefdset;
3002 fd_set exceptfdset;
3003 FD_ZERO(&readfdset);
3004 FD_ZERO(&writefdset);
3005 FD_ZERO(&exceptfdset);
3006 for(unsigned int i = 0; i < count; i++) {
3007 if((fdlist[i].fd >= 0) && (fdlist[i].fd < (const int)FD_SETSIZE)) {
3008 if(fdlist[i].events & POLLIN) {
3009 FD_SET(fdlist[i].fd,&readfdset);
3010 }
3011 if(fdlist[i].events & POLLOUT) {
3012 FD_SET(fdlist[i].fd,&writefdset);
3013 }
3014 FD_SET(fdlist[i].fd,&exceptfdset);
3015 n = std::max(n, fdlist[i].fd);
3016 fdcount++;
3017 }
3018 else {
3019 fdlist[i].revents = POLLNVAL;
3020 }
3021 }
3022 if(fdcount == 0) {
3023 return(0);
3024 }
3025 for(unsigned int i = 0;i < count;i++) {
3026 fdlist[i].revents = 0;
3027 }
3028
3029 // ====== Do ext_select() ================================================
3030 int result = ext_select(n + 1,&readfdset,&writefdset,&exceptfdset,to);
3031 if(result < 0) {
3032 return(result);
3033 }
3034
3035 // ====== Set result flags ===============================================
3036 result = 0;
3037 for(unsigned int i = 0;i < count;i++) {
3038 if((fdlist[i].fd >= 0) && (fdlist[i].fd < (const int)FD_SETSIZE)) {
3039 fdlist[i].revents = 0;
3040 if(SAFE_FD_ISSET(fdlist[i].fd,&readfdset) && (fdlist[i].events & POLLIN)) {
3041 fdlist[i].revents |= POLLIN;
3042 }
3043 if(SAFE_FD_ISSET(fdlist[i].fd,&writefdset) && (fdlist[i].events & POLLOUT)) {
3044 fdlist[i].revents |= POLLOUT;
3045 }
3046 if(SAFE_FD_ISSET(fdlist[i].fd,&exceptfdset)) {
3047 fdlist[i].revents |= POLLERR;
3048 }
3049 if(fdlist[i].revents != 0) {
3050 result++;
3051 }
3052 }
3053 }
3054 return(result);
3055 }
3056
3057
3058 // ###### Check, if SCTP is available #######################################
sctp_isavailable()3059 int sctp_isavailable()
3060 {
3061 return(SCTPSocketMaster::InitializationResult == 0);
3062 }
3063
3064
3065 // ###### Peel association off ##############################################
sctp_peeloff(int sockfd,sctp_assoc_t id)3066 int sctp_peeloff(int sockfd,
3067 sctp_assoc_t id)
3068 {
3069 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
3070 if(tdSocket != NULL) {
3071 switch(tdSocket->Type) {
3072 case ExtSocketDescriptor::ESDT_SCTP:
3073 {
3074 SCTPAssociation* association = NULL;
3075 if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
3076 if(tdSocket->Socket.SCTPSocketDesc.Type != SOCK_STREAM) {
3077 association = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->peelOff(id);
3078 }
3079 }
3080
3081 if(association != NULL) {
3082 ExtSocketDescriptor newExtSocketDescriptor = *tdSocket;
3083 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPSocketPtr = tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr;
3084 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr = association;
3085 newExtSocketDescriptor.Socket.SCTPSocketDesc.ConnectionOriented = true;
3086 const int newFD = ExtSocketDescriptorMaster::setSocket(newExtSocketDescriptor);
3087 if(newFD < 0) {
3088 delete newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr;
3089 newExtSocketDescriptor.Socket.SCTPSocketDesc.SCTPAssociationPtr = NULL;
3090 }
3091 errno_return(newFD);
3092 }
3093 errno_return(-EINVAL);
3094 }
3095 default:
3096 errno_return(-EOPNOTSUPP);
3097 break;
3098 }
3099 }
3100 return(-EBADF);
3101 }
3102
3103
3104 // ###### sctp_getpaddrs() implementation ###################################
sctp_getlpaddrs(int sockfd,sctp_assoc_t id,struct sockaddr ** packedAddrs,const bool peerAddresses)3105 int sctp_getlpaddrs(int sockfd,
3106 sctp_assoc_t id,
3107 struct sockaddr** packedAddrs,
3108 const bool peerAddresses)
3109 {
3110 sockaddr_storage* addrs = NULL;
3111
3112 *packedAddrs = NULL;
3113 ExtSocketDescriptor* tdSocket = ExtSocketDescriptorMaster::getSocket(sockfd);
3114 if(tdSocket != NULL) {
3115 switch(tdSocket->Type) {
3116 case ExtSocketDescriptor::ESDT_SCTP:
3117 {
3118 int result = -ENXIO;
3119 SocketAddress** addressArray = NULL;
3120
3121 // ====== Get local or peer addresses ========================
3122 if(peerAddresses) {
3123 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
3124 if((id != 0) && (tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getID() != id)) {
3125 result = -EINVAL;
3126 }
3127 else {
3128 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getRemoteAddresses(addressArray);
3129 }
3130 }
3131 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
3132 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getRemoteAddresses(addressArray,id);
3133 }
3134 else {
3135 result = -EBADF;
3136 }
3137 }
3138 else {
3139 if(tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr != NULL) {
3140 tdSocket->Socket.SCTPSocketDesc.SCTPAssociationPtr->getLocalAddresses(addressArray);
3141 }
3142 else if(tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr != NULL) {
3143 tdSocket->Socket.SCTPSocketDesc.SCTPSocketPtr->getLocalAddresses(addressArray);
3144 }
3145 else {
3146 result = -EBADF;
3147 }
3148 }
3149
3150 // ====== Copy addresses into sockaddr_storage array =========
3151 if(addressArray != NULL) {
3152 cardinal count = 0;
3153 while(addressArray[count] != NULL) {
3154 count++;
3155 }
3156 if(count > 0) {
3157 result = (int)count;
3158 addrs = new sockaddr_storage[count];
3159 if(addrs != NULL) {
3160 sockaddr* ptr = (sockaddr*)addrs;
3161 for(cardinal i = 0;i < count;i++) {
3162 int family = addressArray[i]->getFamily();
3163 if(family == AF_INET6) {
3164 if(addressArray[i]->getSystemAddress(
3165 ptr,
3166 sizeof(sockaddr_storage),
3167 AF_INET) > 0) {
3168 family = AF_INET;
3169 }
3170 }
3171 if(addressArray[i]->getSystemAddress(
3172 ptr,
3173 sizeof(sockaddr_storage),
3174 family) <= 0) {
3175 result = -ENAMETOOLONG;
3176 delete addrs;
3177 addrs = NULL;
3178 break;
3179 }
3180 ptr = (sockaddr*)((long)ptr + (long)sizeof(sockaddr_storage));
3181 }
3182 }
3183 else {
3184 result = -ENOMEM;
3185 }
3186 }
3187 }
3188
3189 SocketAddress::deleteAddressList(addressArray);
3190 if(addrs) {
3191 *packedAddrs = pack_sockaddr_storage(addrs, result);
3192 delete [] addrs;
3193 }
3194 errno_return(result);
3195 }
3196 break;
3197 case ExtSocketDescriptor::ESDT_System:
3198 errno_return(-EOPNOTSUPP);
3199 break;
3200 }
3201 errno_return(-ENXIO);
3202 }
3203 errno_return(-EBADF);
3204 }
3205
3206
3207 // ###### sctp_getpaddrs() implementation ###################################
sctp_getpaddrs(int sockfd,sctp_assoc_t id,struct sockaddr ** addrs)3208 int sctp_getpaddrs(int sockfd, sctp_assoc_t id, struct sockaddr** addrs)
3209 {
3210 return(sctp_getlpaddrs(sockfd,id,addrs,true));
3211 }
3212
3213
3214 // ###### sctp_freepaddrs() #################################################
sctp_freepaddrs(struct sockaddr * addrs)3215 void sctp_freepaddrs(struct sockaddr* addrs)
3216 {
3217 delete [] addrs;
3218 }
3219
3220
3221 // ###### sctp_getladdrs() implementation ###################################
sctp_getladdrs(int sockfd,sctp_assoc_t id,struct sockaddr ** addrs)3222 int sctp_getladdrs(int sockfd, sctp_assoc_t id, struct sockaddr** addrs)
3223 {
3224 return(sctp_getlpaddrs(sockfd,id,addrs,false));
3225 }
3226
3227
3228 // ###### sctp_freeladdrs() #################################################
sctp_freeladdrs(struct sockaddr * addrs)3229 void sctp_freeladdrs(struct sockaddr* addrs)
3230 {
3231 delete [] addrs;
3232 }
3233
3234
3235 // ###### sctp_opt_info() implementation ####################################
sctp_opt_info(int sd,sctp_assoc_t assocID,int opt,void * arg,socklen_t * size)3236 int sctp_opt_info(int sd, sctp_assoc_t assocID,
3237 int opt, void* arg, socklen_t* size)
3238 {
3239 if((opt == SCTP_RTOINFO) ||
3240 (opt == SCTP_ASSOCINFO) ||
3241 (opt == SCTP_STATUS) ||
3242 (opt == SCTP_GET_PEER_ADDR_INFO)) {
3243 *(sctp_assoc_t *)arg = assocID;
3244 return(ext_getsockopt(sd,IPPROTO_SCTP,opt,arg,size));
3245 }
3246 else if((opt == SCTP_PRIMARY_ADDR) ||
3247 (opt == SCTP_SET_PEER_PRIMARY_ADDR) ||
3248 (opt == SCTP_SET_STREAM_TIMEOUTS) ||
3249 (opt == SCTP_PEER_ADDR_PARAMS)) {
3250 return(ext_setsockopt(sd,IPPROTO_SCTP,opt,arg,*size));
3251 }
3252 else {
3253 errno_return(-EOPNOTSUPP);
3254 }
3255 }
3256
3257
3258 // ###### sctp_sendmsg() implementation #####################################
sctp_sendmsg(int s,const void * data,size_t len,const struct sockaddr * to,socklen_t tolen,uint32_t ppid,uint32_t flags,uint16_t stream_no,uint32_t timetolive,uint32_t context)3259 ssize_t sctp_sendmsg(int s,
3260 const void* data,
3261 size_t len,
3262 const struct sockaddr* to,
3263 socklen_t tolen,
3264 uint32_t ppid,
3265 uint32_t flags,
3266 uint16_t stream_no,
3267 uint32_t timetolive,
3268 uint32_t context)
3269 {
3270 sctp_sndrcvinfo* sri;
3271 struct iovec iov = { (char*)data, len };
3272 struct cmsghdr* cmsg;
3273 size_t cmsglen = CSpace(sizeof(struct sctp_sndrcvinfo));
3274 char cbuf[CSpace(sizeof(struct sctp_sndrcvinfo))];
3275 struct msghdr msg = {
3276 #ifdef __APPLE__
3277 (char*)to,
3278 #else
3279 (struct sockaddr*)to,
3280 #endif
3281 tolen,
3282 &iov, 1,
3283 cbuf,
3284 #ifdef __FreeBSD__
3285 (socklen_t)cmsglen,
3286 #else
3287 cmsglen,
3288 #endif
3289 (int)flags
3290 };
3291
3292 cmsg = (struct cmsghdr*)CFirstHeader(&msg);
3293 cmsg->cmsg_len = CLength(sizeof(struct sctp_sndrcvinfo));
3294 cmsg->cmsg_level = IPPROTO_SCTP;
3295 cmsg->cmsg_type = SCTP_SNDRCV;
3296
3297 sri = (struct sctp_sndrcvinfo*)CData(cmsg);
3298 sri->sinfo_assoc_id = 0;
3299 sri->sinfo_stream = stream_no;
3300 sri->sinfo_ppid = ppid;
3301 sri->sinfo_flags = flags;
3302 sri->sinfo_ssn = 0;
3303 sri->sinfo_tsn = 0;
3304 sri->sinfo_context = 0;
3305 sri->sinfo_cumtsn = 0;
3306 sri->sinfo_timetolive = timetolive;
3307
3308 return(ext_sendmsg(s, &msg, 0));
3309 }
3310
3311
3312 // ###### sctp_send() implementation ########################################
sctp_send(int s,const void * data,size_t len,const struct sctp_sndrcvinfo * sinfo,int flags)3313 ssize_t sctp_send(int s,
3314 const void* data,
3315 size_t len,
3316 const struct sctp_sndrcvinfo* sinfo,
3317 int flags)
3318 {
3319 sctp_sndrcvinfo* sri;
3320 struct iovec iov = { (char*)data, len };
3321 struct cmsghdr* cmsg;
3322 size_t cmsglen = CSpace(sizeof(struct sctp_sndrcvinfo));
3323 char cbuf[CSpace(sizeof(struct sctp_sndrcvinfo))];
3324 struct msghdr msg = {
3325 NULL, 0,
3326 &iov, 1,
3327 cbuf,
3328 #ifdef __FreeBSD__
3329 (socklen_t)cmsglen,
3330 #else
3331 cmsglen,
3332 #endif
3333 flags
3334 };
3335
3336 cmsg = (struct cmsghdr*)CFirstHeader(&msg);
3337 cmsg->cmsg_len = CLength(sizeof(struct sctp_sndrcvinfo));
3338 cmsg->cmsg_level = IPPROTO_SCTP;
3339 cmsg->cmsg_type = SCTP_SNDRCV;
3340
3341 sri = (struct sctp_sndrcvinfo*)CData(cmsg);
3342 memcpy(sri, sinfo, sizeof(struct sctp_sndrcvinfo));
3343
3344 return(ext_sendmsg(s, &msg, 0));
3345 }
3346
3347
3348 // ###### sctp_sendmsg() implementation #####################################
sctp_sendx(int sd,const void * data,size_t len,const struct sockaddr * addrs,int addrcnt,const struct sctp_sndrcvinfo * sinfo,int flags)3349 ssize_t sctp_sendx(int sd,
3350 const void* data,
3351 size_t len,
3352 const struct sockaddr* addrs,
3353 int addrcnt,
3354 const struct sctp_sndrcvinfo* sinfo,
3355 int flags)
3356 {
3357 sctp_sndrcvinfo* sri;
3358 struct iovec iov = { (char*)data, len };
3359 struct cmsghdr* cmsg;
3360 size_t cmsglen = CSpace(sizeof(struct sctp_sndrcvinfo));
3361 char cbuf[CSpace(sizeof(struct sctp_sndrcvinfo))];
3362 struct msghdr msg = {
3363 #ifdef __APPLE__
3364 (char*)addrs,
3365 #else
3366 (struct sockaddr*)addrs,
3367 #endif
3368 (socklen_t)addrcnt,
3369 &iov, 1,
3370 cbuf,
3371 #ifdef __FreeBSD__
3372 (socklen_t)cmsglen,
3373 #else
3374 cmsglen,
3375 #endif
3376 flags | MSG_MULTIADDRS,
3377 };
3378
3379 cmsg = (struct cmsghdr*)CFirstHeader(&msg);
3380 cmsg->cmsg_len = CLength(sizeof(struct sctp_sndrcvinfo));
3381 cmsg->cmsg_level = IPPROTO_SCTP;
3382 cmsg->cmsg_type = SCTP_SNDRCV;
3383
3384 sri = (struct sctp_sndrcvinfo*)CData(cmsg);
3385 if(sinfo != NULL) {
3386 memcpy(sri, sinfo, sizeof(struct sctp_sndrcvinfo));
3387 }
3388 else {
3389 memset(sri, 0, sizeof(struct sctp_sndrcvinfo));
3390 }
3391 sri->sinfo_flags |= MSG_MULTIADDRS;
3392
3393 return(ext_sendmsg(sd, &msg, 0));
3394 }
3395
3396
3397 // ###### sctp_recvmsg() implementation #####################################
sctp_recvmsg(int s,void * data,size_t len,struct sockaddr * from,socklen_t * fromlen,struct sctp_sndrcvinfo * sinfo,int * msg_flags)3398 ssize_t sctp_recvmsg(int s,
3399 void* data,
3400 size_t len,
3401 struct sockaddr* from,
3402 socklen_t* fromlen,
3403 struct sctp_sndrcvinfo* sinfo,
3404 int* msg_flags)
3405 {
3406 struct iovec iov = { (char*)data, len };
3407 struct cmsghdr* cmsg;
3408 size_t cmsglen = CSpace(sizeof(struct sctp_sndrcvinfo));
3409 char cbuf[CSpace(sizeof(struct sctp_sndrcvinfo))];
3410 struct msghdr msg = {
3411 #ifdef __APPLE__
3412 (char*)from,
3413 #else
3414 from,
3415 #endif
3416 (fromlen != NULL) ? *fromlen : 0,
3417 &iov, 1,
3418 cbuf,
3419 #ifdef __FreeBSD__
3420 (socklen_t)cmsglen,
3421 #else
3422 cmsglen,
3423 #endif
3424 (msg_flags != NULL) ? *msg_flags : 0
3425 };
3426 int cc;
3427
3428 cc = ext_recvmsg(s, &msg, 0);
3429
3430 if((cc > 0) && (msg.msg_control != NULL) && (msg.msg_controllen > 0)) {
3431 cmsg = (struct cmsghdr*)CFirstHeader(&msg);
3432 if((sinfo != NULL) &&
3433 (cmsg != NULL) &&
3434 (cmsg->cmsg_len == CLength(sizeof(struct sctp_sndrcvinfo))) &&
3435 (cmsg->cmsg_level == IPPROTO_SCTP) &&
3436 (cmsg->cmsg_type == SCTP_SNDRCV)) {
3437 *sinfo = *((struct sctp_sndrcvinfo*)CData(cmsg));
3438 }
3439 }
3440 if(msg_flags != NULL) {
3441 *msg_flags = msg.msg_flags;
3442 }
3443 if(fromlen != NULL) {
3444 *fromlen = msg.msg_namelen;
3445 }
3446 return(cc);
3447 }
3448
3449
3450 #else
3451
3452
3453 // ###### Check, if SCTP is available #######################################
sctp_isavailable()3454 int sctp_isavailable()
3455 {
3456 int result = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP);
3457 if(result != -1) {
3458 close(result);
3459 errno_return(1);
3460 }
3461 else {
3462 #ifdef PRINT_NOSCTP_NOTE
3463 std::cerr << "SCTP is unsupported on this host!" << std::endl;
3464 #endif
3465 errno_return(0);
3466 }
3467 }
3468
3469
3470 #endif
3471
3472
3473 // ###### Change OOTB handling ##############################################
sctp_enableOOTBHandling(const unsigned int enable)3474 int sctp_enableOOTBHandling(const unsigned int enable)
3475 {
3476 if(SCTPSocketMaster::enableOOTBHandling(enable != 0) == false) {
3477 return(-EIO);
3478 }
3479 return(0);
3480 }
3481
3482
3483 // ###### Change CRC32 usage ################################################
sctp_enableCRC32(const unsigned int enable)3484 int sctp_enableCRC32(const unsigned int enable)
3485 {
3486 if(SCTPSocketMaster::enableCRC32(enable != 0) == false) {
3487 return(-EIO);
3488 }
3489 return(0);
3490 }
3491