1 /* $Id$
2  * --------------------------------------------------------------------------
3  *
4  *           //=====   //===== ===//=== //===//  //       //   //===//
5  *          //        //         //    //    // //       //   //    //
6  *         //====//  //         //    //===//  //       //   //===<<
7  *              //  //         //    //       //       //   //    //
8  *       ======//  //=====    //    //       //=====  //   //===//
9  *
10  * -------------- An SCTP implementation according to RFC 4960 --------------
11  *
12  * Copyright (C) 2000 by Siemens AG, Munich, Germany.
13  * Copyright (C) 2001-2004 Andreas Jungmaier
14  * Copyright (C) 2004-2019 Thomas Dreibholz
15  *
16  * Acknowledgements:
17  * Realized in co-operation between Siemens AG and the University of
18  * Duisburg-Essen, Institute for Experimental Mathematics, Computer
19  * Networking Technology group.
20  * This work was partially funded by the Bundesministerium fuer Bildung und
21  * Forschung (BMBF) of the Federal Republic of Germany
22  * (Förderkennzeichen 01AK045).
23  * The authors alone are responsible for the contents.
24  *
25  * This library is free software: you can redistribute it and/or modify it
26  * under the terms of the GNU Lesser General Public License as published by
27  * the Free Software Foundation, either version 2.1 of the License, or
28  * (at your option) any later version.
29  *
30  * This library is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33  * GNU General Public License for more details.
34  *
35  * You should have received a copy of the GNU Lesser General Public License
36  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
37  *
38  * Contact: sctp-discussion@sctp.de
39  *          dreibh@iem.uni-due.de
40  *          tuexen@fh-muenster.de
41  *          andreas.jungmaier@web.de
42  */
43 
44 #include "sctp_wrapper.h"
45 
46 #define POLLIN     0x001
47 #define POLLPRI    0x002
48 #define POLLOUT    0x004
49 #define POLLERR    0x008
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 int
SCTP_setLibraryParameters(SCTP_LibraryParameters * params)55 SCTP_setLibraryParameters(SCTP_LibraryParameters *params)
56 {
57     int result;
58 
59     if ((result =  sctp_setLibraryParameters(params)) != SCTP_SUCCESS) {
60       if (result == SCTP_PARAMETER_PROBLEM) {
61         fprintf(stderr, "sctp_setLibraryParameters: parameter problem.\n");
62       } else
63       if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
64         fprintf(stderr, "sctp_setLibraryParameters: Library not initialized.\n");
65       } else {
66         fprintf(stderr, "sctp_setLibraryParameters: unknown value (%i) returned.\n", result);
67       }
68       fflush(stderr);
69       exit(result);
70     }
71     return result;
72 }
73 
74 int
SCTP_getLibraryParameters(SCTP_LibraryParameters * params)75 SCTP_getLibraryParameters(SCTP_LibraryParameters *params)
76 {
77     int result;
78 
79     if ((result =  sctp_getLibraryParameters(params)) != SCTP_SUCCESS) {
80       if (result == SCTP_PARAMETER_PROBLEM) {
81         fprintf(stderr, "sctp_getLibraryParameters: parameter problem.\n");
82       } else
83       if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
84         fprintf(stderr, "sctp_getLibraryParameters: Library not initialized.\n");
85       } else {
86         fprintf(stderr, "sctp_getLibraryParameters: unknown value (%i) returned.\n", result);
87       }
88       fflush(stderr);
89       exit(result);
90     }
91     return result;
92 }
93 
94 int
SCTP_initLibrary(void)95 SCTP_initLibrary(void)
96 {
97     int result;
98 
99     if ((result = sctp_initLibrary()) != SCTP_SUCCESS) {
100         if (result == SCTP_LIBRARY_ALREADY_INITIALIZED) {
101             fprintf(stderr, "sctp_initLibrary: called muliple times.\n");
102         } else
103         if (result == SCTP_INSUFFICIENT_PRIVILEGES) {
104             fprintf(stderr, "sctp_initLibrary: could not open raw socket for SCTP. You must have root provileges !\n");
105         } else
106         if (result == SCTP_SPECIFIC_FUNCTION_ERROR) {
107             fprintf(stderr, "sctp_initLibrary: Unknown error in Adaptation-Module !\n");
108         } else {
109             fprintf(stderr, "sctp_initLibrary: unknown value (%i) returned.\n", result);
110         }
111         fflush(stderr);
112         exit(result);
113     }
114     return result;
115 }
116 
117 int
SCTP_registerInstance(unsigned short port,unsigned short noOfInStreams,unsigned short noOfOutStreams,unsigned int noOfLocalAddresses,unsigned char localAddressList[][SCTP_MAX_IP_LEN],SCTP_ulpCallbacks ULPcallbackFunctions)118 SCTP_registerInstance(unsigned short port,
119                       unsigned short noOfInStreams,
120                       unsigned short noOfOutStreams,
121                       unsigned int noOfLocalAddresses,
122                       unsigned char localAddressList[][SCTP_MAX_IP_LEN],
123                       SCTP_ulpCallbacks ULPcallbackFunctions)
124 {
125     int result;
126 
127     result = sctp_registerInstance(port, noOfInStreams, noOfOutStreams,
128                                    noOfLocalAddresses, localAddressList,
129                                    ULPcallbackFunctions);
130     if (result == SCTP_PARAMETER_PROBLEM) {
131         fprintf(stderr, "sctp_registerInstance: an error occured.\n");
132         fflush(stderr);
133         exit(result);
134     } else if (result == SCTP_WRONG_ADDRESS) {
135         fprintf(stderr, "sctp_registerInstance: you passed an invalid/wrong address.\n");
136         fflush(stderr);
137         exit(result);
138     } else if (result == SCTP_OUT_OF_RESOURCES) {
139         fprintf(stderr, "sctp_registerInstance: you passed an invalid/wrong address.\n");
140         fflush(stderr);
141         exit(result);
142     }
143     return result;
144 }
145 
SCTP_unregisterInstance(unsigned short instance_name)146 int SCTP_unregisterInstance(unsigned short instance_name)
147 {
148     int result;
149 
150     if ((result = sctp_unregisterInstance(instance_name)) != 0) {
151         fprintf(stderr, "sctp_unregisterInstance: an error occured.\n");
152         fflush(stderr);
153     }
154     return result;
155 }
156 
157 int
SCTP_deleteAssociation(unsigned int associationID)158 SCTP_deleteAssociation(unsigned int associationID)
159 {
160     int result;
161 
162     if ((result = sctp_deleteAssociation(associationID))!=0) {
163         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
164             fprintf(stderr, "sctp_deleteAssociation: library not initialized:\n");
165         } else
166         if (result == SCTP_SPECIFIC_FUNCTION_ERROR) {
167             fprintf(stderr, "sctp_deleteAssociation: assoc not ready for deletion or lib not initialized:\n");
168         } else
169         if (result == SCTP_ASSOC_NOT_FOUND) {
170             fprintf(stderr, "sctp_deleteAssociation: assoc does not exists.\n");
171         }
172         fflush(stderr);
173     }
174     return result;
175 }
176 
177 int
SCTP_send(unsigned int associationID,unsigned short streamID,unsigned char * buffer,unsigned int length,unsigned int protocolId,short path_id,void * context,unsigned int lifetime,int unorderedDelivery,int dontBundle)178 SCTP_send(unsigned int associationID, unsigned short streamID,
179           unsigned char *buffer, unsigned int length, unsigned int protocolId, short path_id,
180           void*  context,
181           unsigned int lifetime,
182           int unorderedDelivery,
183           int dontBundle)
184 {
185     int result;
186 
187     if ((result = sctp_send(associationID, streamID,
188                            buffer, length, protocolId, path_id,
189                            context,
190                            lifetime,
191                            unorderedDelivery,
192                            dontBundle))!= SCTP_SUCCESS) {
193         if (result == SCTP_QUEUE_EXCEEDED) {
194 /*          fprintf(stderr, "sctp_send: Queue size exceeded.\n");*/
195         } else
196         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
197             fprintf(stderr, "sctp_send: library not initialized.\n");
198         } else
199         if (result == SCTP_ASSOC_NOT_FOUND) {
200             fprintf(stderr, "sctp_send: association not found.\n");
201         } else
202         if (result == SCTP_SPECIFIC_FUNCTION_ERROR) {
203             fprintf(stderr, "sctp_send: association in shutdown state - don't send any more data !\n");
204         } else
205         if (result == SCTP_MODULE_NOT_FOUND) {
206             fprintf(stderr, "sctp_send: internal error !\n");
207         } else
208         if (result == SCTP_PARAMETER_PROBLEM) {
209             fprintf(stderr, "sctp_send: Parameter Problem (invalid path or stream id).\n");
210         } else {
211             fprintf(stderr, "sctp_send: unkown result (%i) returned.\n", result);
212         }
213         fflush(stderr);
214     }
215     return result;
216 }
217 
218 int
SCTP_receive(unsigned int associationID,unsigned short streamID,unsigned char * buffer,unsigned int * length,unsigned short * streamSN,unsigned int * tsn,unsigned int flags)219 SCTP_receive(unsigned int associationID, unsigned short streamID, unsigned char *buffer,
220 			unsigned int *length, unsigned short* streamSN, unsigned int * tsn, unsigned int flags)
221 {
222     int result;
223 
224     if ((result = sctp_receive(associationID, streamID, buffer, length, streamSN, tsn, flags))!=0) {
225         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
226             fprintf(stderr, "sctp_receive: library not initialized.\n");
227         } else
228         if (result == SCTP_ASSOC_NOT_FOUND) {
229             fprintf(stderr, "sctp_receive: association not found.\n");
230         } else
231         if (result == SCTP_MODULE_NOT_FOUND) {
232             fprintf(stderr, "sctp_receive: internal error.\n");
233         } else
234         if (result == SCTP_SPECIFIC_FUNCTION_ERROR) {
235             /* fprintf(stderr, "sctp_receive: NO DATA AVAILABLE.\n"); */
236         } else
237         if (result == SCTP_PARAMETER_PROBLEM) {
238             fprintf(stderr, "sctp_receive: parameter problem (Null-Pointers, PathID ?)\n");
239         }
240         fflush(stderr);
241     }
242     return result;
243 }
244 
245 int
SCTP_shutdown(unsigned int associationID)246 SCTP_shutdown(unsigned int associationID)
247 {
248     int result;
249 
250     if ((result = sctp_shutdown(associationID))!= SCTP_SUCCESS) {
251         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
252             fprintf(stderr, "sctp_shutdown: library not initialized.\n");
253         } else
254         if (result == SCTP_ASSOC_NOT_FOUND) {
255             fprintf(stderr, "sctp_shutdown: association not found.\n");
256         }
257         fflush(stderr);
258     }
259     return result;
260 }
261 
262 int
SCTP_abort(unsigned int associationID)263 SCTP_abort(unsigned int associationID)
264 {
265     int result;
266 
267     if ((result = sctp_abort(associationID)) != SCTP_SUCCESS) {
268         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
269             fprintf(stderr, "sctp_abort: library not initialized.\n");
270         } else
271         if (result == SCTP_ASSOC_NOT_FOUND) {
272             fprintf(stderr, "sctp_abort: association not found.\n");
273         }
274         fflush(stderr);
275     }
276     return result;
277 }
278 
SCTP_getAssocStatus(unsigned int associationID,SCTP_AssociationStatus * status)279 int SCTP_getAssocStatus(unsigned int associationID, SCTP_AssociationStatus* status)
280 {
281     int result;
282 
283     if ((result = sctp_getAssocStatus(associationID, status)) != SCTP_SUCCESS) {
284         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
285             fprintf(stderr, "sctp_getAssocStatus: library not initialized.\n");
286         } else
287         if (result == SCTP_ASSOC_NOT_FOUND) {
288             fprintf(stderr, "sctp_getAssocStatus: association not found.\n");
289         } else
290         if (result == SCTP_PARAMETER_PROBLEM) {
291             fprintf(stderr, "sctp_getAssocStatus: parameter problem (NULL pointer ?)\n");
292         } else {
293             fprintf(stderr, "sctp_getAssocStatus: unknown value (%i) returned.\n", result);
294         }
295         fflush(stderr);
296     }
297     return result;
298 }
299 
300 int
SCTP_receiveUnacked(unsigned int associationID,unsigned char * buffer,unsigned int * length,unsigned int * tsn,unsigned short * streamID,unsigned short * streamSN,unsigned int * protocolId)301 SCTP_receiveUnacked(unsigned int associationID, unsigned char *buffer, unsigned int *length, unsigned int* tsn,
302                     unsigned short *streamID, unsigned short *streamSN,unsigned int* protocolId)
303 {
304     int result;
305     unsigned char flags;
306     void* ctx;
307 
308     if ((result = sctp_receiveUnacked(associationID, buffer, length, tsn,
309                                       streamID, streamSN, protocolId, &flags, &ctx)) < 0) {
310 
311         if (result == SCTP_WRONG_STATE) {
312             fprintf(stderr, "SCTP_receiveUnacked: Association is not in state CLOSED. \n");
313         }else if (result ==SCTP_ASSOC_NOT_FOUND){
314             fprintf(stderr, "SCTP_receiveUnacked: Association not found \n");
315         }else if (result == SCTP_NO_CHUNKS_IN_QUEUE){
316             /* fprintf(stderr, "SCTP_receiveUnacked: Queue is already empty.\n"); */
317         }else if (result == SCTP_LIBRARY_NOT_INITIALIZED){
318             fprintf(stderr, "SCTP_receiveUnacked: Library not Initialized \n");
319         }else if (result == SCTP_PARAMETER_PROBLEM){
320             fprintf(stderr, "SCTP_receiveUnacked: parameter problem, NULL pointer passed ?\n");
321         } else {
322             fprintf(stderr, "SCTP_receiveUnacked: unknown value (%i) returned.\n", result);
323         }
324         fflush(stderr);
325     }
326     return result;
327 }
328 
329 int
SCTP_receiveUnsent(unsigned int associationID,unsigned char * buffer,unsigned int * length,unsigned int * tsn,unsigned short * streamID,unsigned short * streamSN,unsigned int * protocolId)330 SCTP_receiveUnsent(unsigned int associationID, unsigned char *buffer, unsigned int *length, unsigned int* tsn,
331                    unsigned short *streamID, unsigned short *streamSN,unsigned int* protocolId)
332 {
333     int result;
334     unsigned char flags;
335     void* ctx;
336 
337     if ((result = sctp_receiveUnsent(associationID, buffer, length, tsn,
338                                      streamID, streamSN, protocolId, &flags, &ctx)) < 0) {
339         if (result == SCTP_WRONG_STATE) {
340             fprintf(stderr, "sctp_receiveUnsent: Association is not in state CLOSED. \n");
341         }else if (result ==SCTP_ASSOC_NOT_FOUND){
342             fprintf(stderr, "sctp_receiveUnsent: Association not found \n");
343         }else if (result == SCTP_PARAMETER_PROBLEM){
344             fprintf(stderr, "sctp_receiveUnsent: parameter problem, NULL pointer passed ?\n");
345         }else if (result == SCTP_LIBRARY_NOT_INITIALIZED){
346             fprintf(stderr, "sctp_receiveUnsent: Library not Initialized.\n");
347         }else if (result == SCTP_NO_CHUNKS_IN_QUEUE){
348             /* fprintf(stderr, "sctp_receiveUnsent: Queue is already empty.\n"); */
349         } else {
350             fprintf(stderr, "sctp_receiveUnsent: unknown value (%i) returned.\n", result);
351         }
352         fflush(stderr);
353     }
354     return result;
355 }
356 
357 short
SCTP_setPrimary(unsigned int associationID,short path_id)358 SCTP_setPrimary(unsigned int associationID, short path_id)
359 {
360     int result;
361 
362     if ((result = sctp_setPrimary(associationID, path_id)) != 0) {
363         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
364             fprintf(stderr, "sctp_setPrimary: library not initialized.\n");
365         } else
366         if (result == SCTP_ASSOC_NOT_FOUND) {
367             fprintf(stderr, "sctp_setPrimary: association not found.\n");
368         } else
369         if (result == SCTP_MODULE_NOT_FOUND) {
370             fprintf(stderr, "sctp_setPrimary: internal error.\n");
371         } else
372         if (result == SCTP_UNSPECIFIED_ERROR) {
373             fprintf(stderr, "sctp_setPrimary: internal error (data structure not yet allocated).\n");
374         } else
375         if (result == SCTP_PARAMETER_PROBLEM) {
376             fprintf(stderr, "sctp_setPrimary: Path Id invalid.\n");
377         } else
378         if (result == SCTP_SPECIFIC_FUNCTION_ERROR) {
379             fprintf(stderr, "sctp_setPrimary: association is not in state established, or primary path inactive\n");
380         }
381         fflush(stderr);
382     }
383     return result;
384 }
385 
386 short
SCTP_getPrimary(unsigned int associationID)387 SCTP_getPrimary(unsigned int associationID)
388 {
389     int result;
390 
391     if ((result = sctp_getPrimary(associationID)) < 0) {
392         fprintf(stderr, "sctp_setPrimary: error value (%i) returned.\n", result);
393         fflush(stderr);
394     }
395     return result;
396 }
397 
398 int
SCTP_eventLoop(void)399 SCTP_eventLoop(void)
400 {
401     int result;
402 
403     if ((result = sctp_eventLoop()) < 0) {
404         if (result == -1) {
405             fprintf(stderr, "sctp_eventLoop: an error occured.\n");
406         } else {
407             fprintf(stderr, "sctp_eventLoop: unknown value (%i) returned.\n", result);
408         }
409         fflush(stderr);
410     }
411     return result;
412 }
413 
414 int
SCTP_getPathStatus(unsigned int associationID,short path_id,SCTP_PathStatus * status)415 SCTP_getPathStatus(unsigned int associationID, short path_id, SCTP_PathStatus* status)
416 {
417     int result;
418 
419     if ((result = sctp_getPathStatus(associationID, path_id, status)) != 0) {
420         if (result == SCTP_LIBRARY_NOT_INITIALIZED) {
421             fprintf(stderr, "sctp_getP: library not initialized.\n");
422         } else
423         if (result == SCTP_ASSOC_NOT_FOUND) {
424             fprintf(stderr, ": association not found.\n");
425         } else
426         if (result == SCTP_PARAMETER_PROBLEM) {
427             fprintf(stderr, ": Path Id invalid.\n");
428         } else {
429             fprintf(stderr, "sctp_getPathStatus: error value (%i) returned.\n", result);
430             fflush(stderr);
431         }
432     }
433     return result;
434 }
435 
436 unsigned int
SCTP_associate(unsigned short SCTP_InstanceName,unsigned short noOfOutStreams,unsigned char destinationAddress[],unsigned short destinationPort,void * ulp_data)437 SCTP_associate(unsigned short SCTP_InstanceName,
438                unsigned short noOfOutStreams,
439                unsigned char destinationAddress[],
440                unsigned short destinationPort,
441                void* ulp_data)
442 {
443     unsigned short result;
444 
445     if ((result = sctp_associate(SCTP_InstanceName,
446                                  noOfOutStreams,
447                                  destinationAddress,
448                                  destinationPort,
449                                  ulp_data)) == 0) {
450         fprintf(stderr, "sctp_associate: an error occured.\n");
451         fflush(stderr);
452     }
453     return result;
454 }
455 
456 
SCTP_changeHeartBeat(unsigned int associationID,short path_id,int heartbeatON,unsigned int timeInterval)457 int SCTP_changeHeartBeat(unsigned int associationID,
458                          short path_id, int heartbeatON, unsigned int timeInterval)
459 {
460     int result;
461 
462     if ((result = sctp_changeHeartBeat(associationID, path_id, heartbeatON, timeInterval)) < 0) {
463         fprintf(stderr, "sctp_changeHeartBeat: an error occured.\n");
464         fflush(stderr);
465     }
466     return result;
467 }
468 
469 int
SCTP_registerStdinCallback(sctp_StdinCallback sdf,char * buffer,int length)470 SCTP_registerStdinCallback(sctp_StdinCallback sdf, char* buffer, int length)
471 {
472     int result;
473 
474     if ((result = sctp_registerStdinCallback(sdf, buffer, length)) < 0) {
475         fprintf(stderr, "sctp_registerStdinCallback: error value (%i) returned.\n", result);
476         fflush(stderr);
477     }
478     return result;
479 }
480 
SCTP_unregisterStdinCallback()481 int SCTP_unregisterStdinCallback()
482 {
483     int result;
484 
485     if ((result = sctp_unregisterStdinCallback()) < 0) {
486         fprintf(stderr, "sctp_unregisterStdinCallback: error value (%i) returned.\n", result);
487         fflush(stderr);
488     }
489     return result;
490 }
491 
492 #ifndef WIN32
493 int
SCTP_registerUserCallback(int fd,sctp_userCallback sdf,void * userData)494 SCTP_registerUserCallback(int fd, sctp_userCallback sdf, void* userData)
495 {
496     int result;
497 
498     if ((result = sctp_registerUserCallback(fd, sdf, userData, POLLIN|POLLPRI)) < 0) {
499         fprintf(stderr, "sctp_registerUserCallback: error value (%i) returned.\n", result);
500         fflush(stderr);
501     }
502     return result;
503 }
504 #endif
505 
506 int
SCTP_getAssocDefaults(unsigned short SCTP_InstanceName,SCTP_InstanceParameters * params)507 SCTP_getAssocDefaults(unsigned short SCTP_InstanceName, SCTP_InstanceParameters* params)
508 {
509     int result;
510 
511     if ((result = sctp_getAssocDefaults(SCTP_InstanceName, params)) != 0) {
512         fprintf(stderr, "sctp_getAssocDefaults: error value (%i) returned.\n", result);
513         fflush(stderr);
514     }
515     return result;
516 }
517 
518 int
SCTP_setAssocDefaults(unsigned short SCTP_InstanceName,SCTP_InstanceParameters * params)519 SCTP_setAssocDefaults(unsigned short SCTP_InstanceName, SCTP_InstanceParameters* params)
520 {
521     int result;
522 
523     if ((result = sctp_setAssocDefaults(SCTP_InstanceName, params)) != 0) {
524         fprintf(stderr, "sctp_setAssocDefaults: error value (%i) returned.\n", result);
525         fflush(stderr);
526     }
527     return result;
528 }
529 
530 unsigned int
SCTP_startTimer(unsigned int milliseconds,sctp_timerCallback timer_cb,void * param1,void * param2)531 SCTP_startTimer(unsigned int milliseconds, sctp_timerCallback timer_cb,
532                 void *param1, void *param2)
533 {
534      return sctp_startTimer(milliseconds/1000, (milliseconds%1000)*1000, timer_cb, param1, param2);
535 }
536 
537