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 "globals.h"
45 #include "adaptation.h"
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #include <time.h>
50 #include <sys/types.h>
51 
52 #ifdef HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif
55 
56 #ifdef WIN32
57 #include <process.h>
58 #endif
59 
60 
61 boolean globalTrace;
62 boolean fileTrace = FALSE;
63 FILE* logfile;
64 static int noOftracedModules;
65 static char tracedModules[50][70];
66 static int errorTraceLevel[50];
67 static int eventTraceLevel[50];
68 
69 /**
70  * helper function for sorting list of chunks in tsn order
71  * @param  one pointer to chunk data
72  * @param  two pointer to other chunk data
73  * @return 0 if chunks have equal tsn, -1 if tsn1 < tsn2, 1 if tsn1 > tsn2
74  */
sort_tsn(chunk_data * one,chunk_data * two)75 int sort_tsn(chunk_data * one, chunk_data * two)
76 {
77     if (before(one->chunk_tsn, two->chunk_tsn)) {
78         return -1;
79     } else if (after(one->chunk_tsn, two->chunk_tsn)) {
80         return 1;
81     } else                      /* one==two */
82         return 0;
83 }
84 
sort_prChunk(pr_stream_data * one,pr_stream_data * two)85 int sort_prChunk(pr_stream_data* one, pr_stream_data* two)
86 {
87     if (one->stream_id < two->stream_id) {
88         return -1;
89     } else if (one->stream_id > two->stream_id) {
90         return 1;
91     } else  /* one.sid==two.sid */ {
92         if (sBefore(one->stream_sn, two->stream_sn)) return -1;
93         else if (sAfter(one->stream_sn, two->stream_sn)) return 1;
94     }
95     return 0;
96 }
97 
98 
99 /**
100    read_tracelevels reads from a file the tracelevels for errors and events for each module.
101    Modules that are not listed in the file will not be traced. if the file does not exist or
102    is empty, the global tracelevel defined in globals.h will be used. THe name of the file has
103    to be {\texttt tracelevels.in} in the current directory where the executable is located.
104    The normal format of the file is:
105    \begin{verbatim}
106    module1.c errorTraceLevel eventTraceLevel
107    module2.c errorTraceLevel eventTraceLevel
108    ....
109    \end{verbatim}
110    The file must be terminated by a null line.
111     Alternatively there may be the entry
112    \begin{verbatim}
113     LOGFILE
114    \end{verbatim}
115     in that file, which causes all output from event_logs() to go into a logfile in the local
116     directory.
117 */
read_tracelevels()118 void read_tracelevels()
119 {
120     FILE *fptr;
121     int i;
122     char filename[100];
123 
124     noOftracedModules = 0;
125     fptr = fopen("./tracelevels.in", "r");
126 
127     if (fptr != NULL) {
128         globalTrace = TRUE;
129 
130         for (i = 0; i < 50; i++) {
131             if(fscanf(fptr, "%s %d %d", tracedModules[i], &errorTraceLevel[i], &eventTraceLevel[i]) >= 1) {
132                if (strcmp(tracedModules[i], "LOGFILE") == 0) {
133                    /*
134                    printf("Logging all errors and events to file ./tmp%d.log\n", (int)getpid());
135                    */
136                    fileTrace = TRUE;
137                    sprintf(filename, "./tmp%d.log",(int)getpid());
138                    logfile = fopen(filename, "w+");
139                    return;
140                }
141             }
142             if (ferror(fptr))
143                 abort();
144             if (feof(fptr))
145                 break;
146             globalTrace = FALSE;
147         }
148         noOftracedModules = i;
149         if (i<= 1) globalTrace = TRUE;
150         /*
151         printf("  globalTrace = %s \n",  (globalTrace==TRUE)?"TRUE":"FALSE");
152         */
153     } else {
154         globalTrace = TRUE; /* ??? */
155     }
156     /*
157     printf("global = %d, #of modules = %d\n", (int) globalTrace, noOftracedModules);
158     for (i = 0; i < noOftracedModules; i++)
159       printf("%20s %2d %2d\n", tracedModules[i], errorTraceLevel[i], eventTraceLevel[i]);
160     */
161 }
162 
163 
164 
traceModule(const char * moduleName,int * moduleIndex)165 boolean traceModule(const char *moduleName, int *moduleIndex)
166 {
167     int i;
168     boolean found;
169 
170     found = FALSE;
171 
172     for (i = 0; i < noOftracedModules; i++)
173         if (!strcmp(tracedModules[i], moduleName)) {
174             found = TRUE;
175             break;
176         }
177 
178     *moduleIndex = i;
179 
180     return found;
181 }
182 
183 
184 
185 
debug_vwrite(FILE * fd,const char * format,va_list ap)186 int debug_vwrite(FILE * fd, const char *format, va_list ap)
187 {
188     struct timeval tv;
189     struct tm *the_time;
190 
191     adl_gettime(&tv);
192     the_time = localtime((time_t *) & (tv.tv_sec));
193 
194     if (fprintf(fd, "%02d:%02d:%02d.%03d - ",
195                 the_time->tm_hour,
196                 the_time->tm_min, the_time->tm_sec, (int) (tv.tv_usec / 1000)) < 1)
197         return (-1);
198     if (vfprintf(fd, format, ap) < 1)
199         return (-1);
200     return (0);
201 }
202 
203 
debug_print(FILE * fd,const char * f,...)204 void debug_print(FILE * fd, const char *f, ...)
205 {
206     va_list va;
207     va_start(va, f);
208     debug_vwrite(fd, f, va);
209     va_end(va);
210     fflush(fd);
211     return;
212 }
213 
214 
215 
perr_exit(const char * infostring)216 void perr_exit(const char *infostring)
217 {
218     perror(infostring);
219     abort();
220 }
221 
222 
print_time(short level)223 void print_time(short level)
224 {
225     struct timeval now;
226 
227     adl_gettime(&now);
228     event_logii(level, "Time now: %ld sec, %ld usec \n", now.tv_sec, now.tv_usec);
229 }
230 
231 
232 
233 /**
234   This function logs events.
235    @param event_log_level  INTERNAL_EVENT_0 INTERNAL_EVENT_1 EXTERNAL_EVENT_X EXTERNAL_EVENT
236    @param module_name      the name of the module that received the event.
237    @param log_info         the info that is printed with the modulename.
238    @param anyno            optional pointer to unsigned int, which is printed along with log_info.
239                             The conversion specification must be contained in log_info.
240 */
event_log1(short event_log_level,const char * module_name,const char * log_info,...)241 void event_log1(short event_log_level, const char *module_name, const char *log_info, ...)
242 {
243     int mi;
244     struct timeval tv;
245     struct tm *the_time;
246 
247     va_list va;
248 
249     va_start(va, log_info);
250 
251     if ((globalTrace && event_log_level <= Current_event_log_) ||
252         (!globalTrace && traceModule(module_name, &mi)
253          && event_log_level <= eventTraceLevel[mi])) {
254 
255         if (event_log_level < VERBOSE) {
256             if (fileTrace == TRUE) {
257                 debug_print(logfile, "Event in Module: %s............\n", module_name);
258             } else {
259                 debug_print(stdout, "Event in Module: %s............\n", module_name);
260             }
261         }
262         adl_gettime(&tv);
263         the_time = localtime((time_t *) & (tv.tv_sec));
264         if (fileTrace == TRUE) {
265             fprintf(logfile, "%02d:%02d:%02d.%03d - ",
266                     the_time->tm_hour, the_time->tm_min, the_time->tm_sec, (int) (tv.tv_usec / 1000));
267             vfprintf(logfile, log_info, va);
268             fprintf(logfile, "\n");
269             fflush(logfile);
270         } else {
271             fprintf(stdout, "%02d:%02d:%02d.%03d - ",
272                     the_time->tm_hour, the_time->tm_min, the_time->tm_sec, (int) (tv.tv_usec / 1000));
273             vfprintf(stdout, log_info, va);
274             fprintf(stdout, "\n");
275             fflush(stdout);
276         }
277     }
278     va_end(va);
279     return;
280 }
281 
282 
283 
284 
285 /**
286    This function logs errors.
287    @param error_log_level  ERROR_MINOR ERROR_MAJOR ERROR_FATAL
288    @param module_name      the name of the module that received the event.
289    @param line_no          the line number within above module.
290    @param log_info         the info that is printed with the modulename.
291    @param anyno            optional pointer to unsigned int, which is printed along with log_info.
292                            The conversion specification must be contained in log_info.
293 
294 */
error_log1(short error_log_level,const char * module_name,int line_no,const char * log_info,...)295 void error_log1(short error_log_level, const char *module_name, int line_no, const char *log_info, ...)
296 {
297     int mi;
298     va_list va;
299 
300     va_start(va, log_info);
301 
302     if ((globalTrace && error_log_level <= Current_error_log_) ||
303         (!globalTrace && traceModule(module_name, &mi)
304          && error_log_level <= eventTraceLevel[mi])) {
305         if (fileTrace == TRUE) {
306             if (error_log_level > ERROR_MINOR)
307             debug_print(logfile,
308                         "+++++++++++++++  Error (Level %2d) in %s at line %d  +++++++++++++++++++\n",
309                         error_log_level, module_name, line_no);
310             fprintf(logfile, "Error Info: ");
311             debug_vwrite(logfile, log_info, va);
312             fprintf(logfile, "\n");
313         } else {
314             if (error_log_level > ERROR_MINOR)
315             debug_print(stderr,
316                         "+++++++++++++++  Error (Level %2d) in %s at line %d  +++++++++++++++++++\n",
317                         error_log_level, module_name, line_no);
318             fprintf(stderr, "Error Info: ");
319             debug_vwrite(stderr, log_info, va);
320             fprintf(stderr, "\n");
321         }
322     }
323     va_end(va);
324     if (fileTrace == TRUE) {
325        fflush(logfile);
326     } else {
327        fflush(stderr);
328     }
329     if (error_log_level == ERROR_FATAL) {
330         abort();
331     }
332 }
333 
334 /**
335    This function logs system call errors. It calls error_log.
336    @param error_log_level  ERROR_MINOR ERROR_MAJOR ERROR_FATAL
337    @param module_name      the name of the module that received the event.
338    @param line_no          the line number within above module.
339    @param errnumber        the errno from systemlibrary.
340    @param log_info         the info that is printed with the modulename and error text.
341 */
error_log_sys1(short error_log_level,const char * module_name,int line_no,short errnumber)342 void error_log_sys1(short error_log_level, const char *module_name, int line_no, short errnumber)
343 {
344     error_log1(error_log_level, module_name, line_no, strerror(errnumber));
345 }
346 
347 
348 /**
349  * functions correctly handle wraparound
350  */
before(unsigned int seq1,unsigned int seq2)351 int before(unsigned int seq1, unsigned int seq2)
352 {
353     return (int) (seq1 - seq2) < 0;
354 }
355 
after(unsigned int seq1,unsigned int seq2)356 int after(unsigned int seq1, unsigned int seq2)
357 {
358     return (int) (seq2 - seq1) < 0;
359 }
360 
sAfter(unsigned short seq1,unsigned short seq2)361 int sAfter(unsigned short seq1, unsigned short seq2)
362 {
363     return (int)((short)(seq2 - seq1)) < 0;
364 }
365 
sBefore(unsigned short seq1,unsigned short seq2)366 int sBefore(unsigned short seq1, unsigned short seq2)
367 {
368     return (int)((short) (seq1 - seq2) < 0);
369 }
370 
371 
372 
373 /**
374  *  is s1 <= s2 <= s3 ?
375  */
between(unsigned int seq1,unsigned int seq2,unsigned int seq3)376 int between(unsigned int seq1, unsigned int seq2, unsigned int seq3)
377 {
378     return seq3 - seq1 >= seq2 - seq1;
379 }
380 
free_list_element(gpointer list_element,gpointer user_data)381 void free_list_element(gpointer list_element, gpointer user_data)
382 {
383     chunk_data * chunkd = (chunk_data*) list_element;
384 
385     if (user_data == NULL) {
386         if (list_element != NULL) free (list_element);
387         return;
388     } else if (GPOINTER_TO_INT(user_data) == 1) {   /* call from flowcontrol */
389         if (list_element != NULL) {
390            if (chunkd->num_of_transmissions == 0) free (list_element);
391         }
392     } else if (GPOINTER_TO_INT(user_data) == 2) {   /* call from reltransfer */
393         if (list_element != NULL) {
394            if (chunkd->num_of_transmissions != 0) free (list_element);
395         }
396     }
397 }
398