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 "recvctrl.h"
45 #include "adaptation.h"
46 #include "bundling.h"
47 #include "distribution.h"
48 #include "streamengine.h"
49 #include "SCTP-control.h"
50 
51 #include <glib.h>
52 #include <string.h>
53 
54 /**
55  * this struct contains all necessary data for creating SACKs from received data chunks
56  */
57 typedef struct rxc_buffer_struct
58 {
59     /*@{ */
60     /** */
61     void *sack_chunk;
62     /** */
63     GList *frag_list;
64     /** */
65     GList *dup_list;
66     /** cumulative TSN acked */
67     unsigned int ctsna;
68     /** store lowest tsn value for dups (!) */
69     unsigned int lowest;
70     /** stores highest tsn received so far, taking care of wraps
71         i.e. highest < lowest indicates a wrap */
72     unsigned int highest;
73     /** */
74     boolean contains_valid_sack;
75     /** */
76     boolean timer_running;
77     /** indicates whether a chunk was recvd that is truly new */
78     boolean new_chunk_received;
79     /** timer for delayed sacks */
80     TimerID sack_timer;
81     int datagrams_received;
82      /* either 1 (= sack each data chunk) or 2 (=sack every second chunk)*/
83     unsigned int sack_flag;
84     /** */
85     unsigned int last_address;
86     /** */
87     unsigned int my_association;
88     /** */
89     unsigned int my_rwnd;
90     /** delay for delayed ACK in msecs */
91     unsigned int delay;
92     /** number of dest addresses */
93     unsigned int num_of_addresses;
94     /*@} */
95 } rxc_buffer;
96 
97 
98 /**
99  * function creates and allocs new rxc_buffer structure.
100  * There is one such structure per established association
101  * @param  remote_initial_TSN initial tsn of the peer
102  * @return pointer to the newly created structure
103  */
rxc_new_recvctrl(unsigned int remote_initial_TSN,unsigned int number_of_destination_addresses,void * sctpInstance)104 void *rxc_new_recvctrl(unsigned int remote_initial_TSN, unsigned int number_of_destination_addresses, void* sctpInstance)
105 {
106     rxc_buffer *tmp;
107 /*
108     unsigned int count;
109 */
110     tmp = (rxc_buffer*)malloc(sizeof(rxc_buffer));
111     if (!tmp) error_log(ERROR_FATAL, "Malloc failed");
112 
113     tmp->frag_list = NULL;
114     tmp->dup_list = NULL;
115     tmp->num_of_addresses = number_of_destination_addresses;
116     tmp->sack_chunk = malloc(sizeof(SCTP_sack_chunk));
117     tmp->ctsna = remote_initial_TSN - 1; /* as per section 4.1 */
118     tmp->lowest = remote_initial_TSN - 1;
119     tmp->highest = remote_initial_TSN - 1;
120     tmp->contains_valid_sack = FALSE;
121     tmp->timer_running = FALSE;
122     tmp->datagrams_received = -1;
123     tmp->sack_flag = 2;
124     tmp->last_address = 0;
125     tmp->my_rwnd =  mdi_getDefaultMyRwnd();
126     tmp->delay =    mdi_getDefaultDelay(sctpInstance);
127     tmp->my_association = mdi_readAssociationID();
128     event_logi(VVERBOSE, "RecvControl : Association-ID== %d ", tmp->my_association);
129     if (tmp->my_association == 0)
130         error_log(ERROR_FATAL, "Association was not set, should be......");
131     return (tmp);
132 }
133 
134 /**
135  * function deletes a rxc_buffer structure (when it is not needed anymore)
136  * @param rxc_instance pointer to a rxc_buffer, that was previously created
137  */
rxc_delete_recvctrl(void * rxc_instance)138 void rxc_delete_recvctrl(void *rxc_instance)
139 {
140     rxc_buffer *tmp;
141     tmp = (rxc_buffer *) rxc_instance;
142     event_log(INTERNAL_EVENT_0, "deleting receivecontrol");
143     free(tmp->sack_chunk);
144 
145     if (tmp->timer_running == TRUE) {
146         sctp_stopTimer(tmp->sack_timer);
147         tmp->timer_running = FALSE;
148     }
149 
150     g_list_foreach(tmp->frag_list, &free_list_element, NULL);
151     g_list_free(tmp->frag_list);
152     g_list_foreach(tmp->dup_list, &free_list_element, NULL);
153     g_list_free(tmp->dup_list);
154     free(tmp);
155 }
156 
157 
158 /**
159  * function to find out, whether a chunk is duplicate or not
160  * @param rbuf	instance of rxc_buffer
161  * @param chunk_tsn	tsn we just received
162  * @return the boolean response
163  */
rxc_chunk_is_duplicate(rxc_buffer * rbuf,unsigned int chunk_tsn)164 boolean rxc_chunk_is_duplicate(rxc_buffer * rbuf, unsigned int chunk_tsn)
165 {
166     unsigned int low = rbuf->lowest;
167     unsigned int hi = rbuf->highest;
168     unsigned int ctsna = rbuf->ctsna;
169     fragment32 *frag;
170     GList *temp = NULL;
171 
172     /* Assume, lowest and highest have already been updated */
173     if (between(low, chunk_tsn, ctsna))
174         return TRUE;
175     if (!between(ctsna, chunk_tsn, hi))
176         return FALSE;
177 
178     /* Now check, whether chunk_tsn is in the (sorted !) list of fragments */
179     if (rbuf->frag_list == NULL) /* no fragments ! */
180         return FALSE;
181 
182     /* if we are still here, we need to check, whether chunk_tsn is between any fragment bounds */
183     temp = g_list_first(rbuf->frag_list);
184     while (temp != NULL) {
185         if (temp->data == NULL) {
186             error_log(ERROR_FATAL, "LIST ERROR rxc_chunk_is_duplicate(2)");
187             temp = g_list_next(temp);
188             continue;
189         }
190         frag = (fragment32*) temp->data;
191         if (between(frag->start_tsn, chunk_tsn, frag->stop_tsn))
192             return TRUE;
193         /* assuming an ordered list of fragments */
194         if (after(frag->stop_tsn, chunk_tsn))
195            return FALSE;
196         temp = g_list_next(temp);
197     }
198     /* never reached */
199     error_log(ERROR_MAJOR, "while loop went past end of list....should not have happened !");
200     return FALSE;
201 }
202 
203 /**
204  * Helper function to do the correct update of rxc->lowest
205  * Function is only called, if that is necessary !
206  * @param rbuf	instance of rxc_buffer
207  * @param chunk_tsn	tsn we just received
208  * @return boolean indicating whether lowest was updated or not
209  */
rxc_update_lowest(rxc_buffer * rbuf,unsigned int chunk_tsn)210 boolean rxc_update_lowest(rxc_buffer * rbuf, unsigned int chunk_tsn)
211 {
212     unsigned int low = rbuf->lowest;
213     if (before(chunk_tsn, low)) {
214         rbuf->lowest = chunk_tsn;
215         /* and it must be a duplicate ! */
216         return TRUE;
217     } else
218         return FALSE /* no update of lowest */ ;
219 }
220 
221 /**
222  * Helper function to do the correct update of rxc->highest
223  * Function is only called, if that is necessary !
224  * @param rbuf	instance of rxc_buffer
225  * @param chunk_tsn	tsn we just received
226  * @return boolean indicating whether highest was updated or not
227  */
rxc_update_highest(rxc_buffer * rbuf,unsigned int chunk_tsn)228 boolean rxc_update_highest(rxc_buffer * rbuf, unsigned int chunk_tsn)
229 {
230     unsigned int hi = rbuf->highest;
231     if (after(chunk_tsn, hi)) {
232         rbuf->highest = chunk_tsn;
233         return TRUE;
234     } else
235         return FALSE /* no update of highest */ ;
236 }
237 
rxc_sort_duplicates(duplicate * one,duplicate * two)238 int rxc_sort_duplicates(duplicate * one, duplicate * two)
239 {
240     if (before(one->duplicate_tsn, two->duplicate_tsn)) {
241         return -1;
242     } else if (after(one->duplicate_tsn, two->duplicate_tsn)) {
243          return 1;
244     } else                      /* one==two */
245         return 0;
246 }
247 
rxc_sort_fragments(fragment32 * one,fragment32 * two)248 int rxc_sort_fragments(fragment32 * one, fragment32 * two)
249 {
250     if (before(one->start_tsn, two->start_tsn) && before(one->stop_tsn, two->stop_tsn)) {
251         return -1;
252     } else if (after(one->start_tsn, two->start_tsn) && after(one->stop_tsn, two->stop_tsn)) {
253          return 1;
254     } else                      /* one==two */
255         return 0;
256 }
257 
258 
259 /**
260  * Helper function for inserting chunk_tsn in the list of duplicates
261  * @param rbuf	instance of rxc_buffer
262  * @param chunk_tsn	tsn we just received
263  */
rxc_update_duplicates(rxc_buffer * rbuf,unsigned int ch_tsn)264 void rxc_update_duplicates(rxc_buffer * rbuf, unsigned int ch_tsn)
265 {
266     duplicate* match;
267     GList* current = NULL;
268 
269     current = g_list_first(rbuf->dup_list);
270     while (current != NULL) {
271         match = (duplicate*)current->data;
272         if (ch_tsn == match->duplicate_tsn) return;
273         current = g_list_next(current);
274     }
275     /* its new - add it to the list */
276     match = (duplicate*)malloc(sizeof(duplicate));
277     match->duplicate_tsn = ch_tsn;
278     rbuf->dup_list =  g_list_insert_sorted(rbuf->dup_list, match, (GCompareFunc) rxc_sort_duplicates);
279 
280 }
281 
282 
283 
284 /**
285  * Helper function to do the correct update of rxc->ctsna
286  * @param rbuf	instance of rxc_buffer
287  * @param chunk_tsn	tsn we just received
288  */
rxc_bubbleup_ctsna(rxc_buffer * rbuf)289 void rxc_bubbleup_ctsna(rxc_buffer * rbuf)
290 {
291     fragment32 *frag;
292     GList *temp = NULL, *old = NULL;
293 
294     event_log(INTERNAL_EVENT_0, "Entering rxc_bubbleup_ctsna... ");
295 
296     if (rbuf->frag_list == NULL) return;
297 
298     temp = g_list_first(rbuf->frag_list);
299 
300     while (temp != NULL) {
301         frag = (fragment32*)temp->data;
302         if (frag != NULL){
303             if (rbuf->ctsna + 1 == frag->start_tsn) {
304                 rbuf->ctsna = frag->stop_tsn;
305                 old = temp;
306                 temp = g_list_next(temp);
307                 rbuf->frag_list = g_list_remove_link(rbuf->frag_list, old);
308                 g_list_free_1(old); free(frag);
309             }
310             else
311                 return;
312         } else {
313             error_log(ERROR_FATAL, "rxc_bubbleup_ctsna: fragment data was NULL !!!!!!! ");
314             return;
315         }
316     }  /* end while */
317 }
318 
rxc_update_fragments(rxc_buffer * rbuf,unsigned int ch_tsn)319 boolean rxc_update_fragments(rxc_buffer * rbuf, unsigned int ch_tsn)
320 {
321     unsigned int lo, hi, gapsize;
322     fragment32 *frag=NULL, *new_frag, * lo_frag;
323     GList *current = NULL, *tmp = NULL;
324 
325     event_logi(INTERNAL_EVENT_0, "Entering rxc_update_fragments.tsn==%u.. ", ch_tsn);
326 
327     lo = rbuf->ctsna + 1;
328 
329     current = g_list_first(rbuf->frag_list);
330 
331     while (current != NULL) {
332         frag = (fragment32*)current->data;
333 
334         hi = frag->start_tsn - 1;
335         event_logiii(VVERBOSE, "while-loop: lo=%u, tsn=%u, hi=%u, \n", lo, ch_tsn, hi);
336 
337         if (between(lo, ch_tsn, hi)) {
338             gapsize = hi - lo + 1;
339             if (gapsize > 1) {
340                 event_logi(INTERNAL_EVENT_0, "Value of Gapsize (should be > 1 :) ", gapsize);
341                 if (ch_tsn == hi) {
342                     event_log(VVERBOSE, "ch_tsn==hi....");
343                     frag->start_tsn = ch_tsn;
344                     rbuf->new_chunk_received = TRUE;
345                     return TRUE;
346                 } else if (ch_tsn == lo) {
347                     event_logii(VVERBOSE, "ch_tsn==lo==%u....rbuf->ctsna==%u....", lo, rbuf->ctsna);
348                     if (ch_tsn == (rbuf->ctsna + 1)) {
349                         rbuf->ctsna++;
350                         rbuf->new_chunk_received = TRUE;
351                         return TRUE;
352                     }
353                     current = g_list_previous(current);
354                     if (current==NULL) {
355                         error_log(ERROR_MAJOR, "Error in Fragment List HANDLING - check program");
356                         return FALSE;
357                     }
358                     frag = (fragment32*)current->data;
359                     frag->stop_tsn = ch_tsn;
360                     rbuf->new_chunk_received = TRUE;
361                     return TRUE;
362                 } else {    /* a fragment in between */
363                     new_frag = (fragment32*)malloc(sizeof(fragment32));
364                     new_frag->start_tsn = new_frag->stop_tsn = ch_tsn;
365                     event_log(VVERBOSE, "Inserting new fragment....");
366                     rbuf->frag_list = g_list_insert_sorted(rbuf->frag_list, new_frag, (GCompareFunc) rxc_sort_fragments);
367                     rbuf->new_chunk_received = TRUE;
368                     return FALSE;
369                 }
370             } else {        /*gapsize == 1 */
371                 event_logi(INTERNAL_EVENT_0, "Value of Gapsize (should be 1 :) %u", gapsize);
372                 /* delete fragment, return TRUE */
373                 if (lo == rbuf->ctsna + 1) {
374                     rbuf->ctsna = frag->stop_tsn;
375                     rbuf->frag_list = g_list_remove_link(rbuf->frag_list, current);
376                     g_list_free_1(current); free(frag);
377                     rbuf->new_chunk_received = TRUE;
378                     return TRUE;
379                 } else {
380                     tmp = current;
381                     current = g_list_previous(current);
382                     if (current == NULL) {
383                         error_log(ERROR_MAJOR, "Error 2 in Fragment List HANDLING - check program");
384                         return FALSE;
385                     }
386                     lo_frag = (fragment32*)current->data;
387                     frag->start_tsn = lo_frag->start_tsn;
388                     rbuf->frag_list = g_list_remove_link(rbuf->frag_list, current);
389                     g_list_free_1(current); free(lo_frag);
390                     current = tmp;
391                     rbuf->new_chunk_received = TRUE;
392                     return TRUE;
393                 }
394             }
395         } else {            /* ch_tsn is not in the gap between these two fragments */
396             lo = frag->stop_tsn + 1;
397             event_logi(VVERBOSE, "rxc_update_fragments: Setting lo to %u ", lo);
398         }
399         current = g_list_next(current);
400     }
401 
402     /* (NULL LISTE)  OR  (End of Fragment List was passed) */
403     if (ch_tsn == lo) {
404         /* just increase ctsna, handle rest in separate update_ctsna() */
405         if (ch_tsn == rbuf->ctsna + 1) {
406             event_logi(VVERBOSE, "Updating rbuf->ctsna==%u", ch_tsn);
407             rbuf->ctsna = ch_tsn;
408             rbuf->new_chunk_received = TRUE;
409             return TRUE;
410         }
411         /* Update last fragment....increase stop_tsn by one */
412         current = g_list_last(rbuf->frag_list);
413         if (current == NULL) {
414             error_log(ERROR_MAJOR, "rxc_update_fragments: Went past end of List....");
415             return FALSE;
416         }
417         frag = (fragment32*)current->data;
418         frag->stop_tsn = frag->stop_tsn + 1;
419         rbuf->new_chunk_received = TRUE;
420 
421         event_logiii(VVERBOSE, "Updating last fragment frag.start==%u, frag.stop==%u, tsn=%u",
422                      frag->start_tsn, frag->stop_tsn, ch_tsn);
423         return FALSE;
424     } else {                    /* a new fragment altogether */
425         current = g_list_last(rbuf->frag_list);
426         new_frag = (fragment32*)malloc(sizeof(fragment32));
427         new_frag->start_tsn = ch_tsn;
428         new_frag->stop_tsn = ch_tsn;
429         rbuf->frag_list = g_list_append(rbuf->frag_list, new_frag);
430         event_logiii(VVERBOSE,
431                      "Inserting new  fragment at end...frag.start==%u,frag.stop==%u, tsn=%u",
432                      new_frag->start_tsn, new_frag->stop_tsn, ch_tsn);
433         rbuf->new_chunk_received = TRUE;
434         return FALSE;           /* no ctsna update necessary whatsoever */
435     }
436 }
437 
438 
439 /**
440  * For now this function treats only one incoming data chunk' tsn
441  * @param chunk the data chunk that was received by the bundling
442  */
rxc_data_chunk_rx(SCTP_data_chunk * se_chk,unsigned int ad_idx)443 int rxc_data_chunk_rx(SCTP_data_chunk * se_chk, unsigned int ad_idx)
444 {
445     rxc_buffer *rxc;
446     unsigned int chunk_tsn;
447     unsigned int chunk_len;
448     unsigned int assoc_state;
449     boolean result = FALSE;
450     int bytesQueued = 0;
451     unsigned current_rwnd = 0;
452 
453     event_log(INTERNAL_EVENT_0, "Entering function rxc_data_chunk_rx");
454     rxc = (rxc_buffer *) mdi_readRX_control();
455     if (!rxc) {
456         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
457         return (-1);
458     }
459 
460 
461     /* resetting it */
462     rxc->new_chunk_received = FALSE;
463     rxc->last_address = ad_idx;
464 
465     bytesQueued = se_getQueuedBytes();
466     if (bytesQueued < 0) bytesQueued = 0;
467     if ((unsigned int)bytesQueued > rxc->my_rwnd) {
468         current_rwnd = 0;
469     } else {
470         current_rwnd = rxc->my_rwnd - bytesQueued;
471     }
472 
473     /* do SWS prevention */
474     if (current_rwnd > 0 && current_rwnd <= 2 * MAX_SCTP_PDU) current_rwnd = 1;
475 
476     /*
477      * if any received data chunks have not been acked, sender
478      * should create a SACK and bundle it with the outbound data
479      */
480     rxc->contains_valid_sack = FALSE;
481 
482     chunk_tsn = ntohl(se_chk->tsn);
483     chunk_len = ntohs(se_chk->chunk_length);
484     assoc_state = sci_getState();
485 
486     if ( (after(chunk_tsn, rxc->highest) && current_rwnd == 0) ||
487          (assoc_state == SHUTDOWNRECEIVED) ||
488          (assoc_state == SHUTDOWNACKSENT) ) {
489         /* drop chunk, if either: our rwnd is 0, or we are already shutting down */
490         rxc->new_chunk_received = FALSE;
491         return 1;
492     }
493 
494     /* TODO :  Duplicates : see Note in section 6.2 :  */
495     /*  Note: When a datagram arrives with duplicate DATA chunk(s) and no new
496         DATA chunk(s), the receiver MUST immediately send a SACK with no
497         delay. Normally this will occur when the original SACK was lost, and
498         the peers RTO has expired. The duplicate TSN number(s) SHOULD be
499         reported in the SACK as duplicate.
500      */
501     event_logii(VERBOSE, "rxc_data_chunk_rx : chunk_tsn==%u, chunk_len=%u", chunk_tsn, chunk_len);
502     if (rxc_update_lowest(rxc, chunk_tsn) == TRUE) {
503         /* tsn is even lower than the lowest one received so far */
504         rxc_update_duplicates(rxc, chunk_tsn);
505     } else if (rxc_update_highest(rxc, chunk_tsn) == TRUE) {
506         rxc->new_chunk_received = TRUE;
507         result = rxc_update_fragments(rxc, chunk_tsn);
508     } else if (rxc_chunk_is_duplicate(rxc, chunk_tsn) == TRUE)
509         rxc_update_duplicates(rxc, chunk_tsn);
510     else
511         result = rxc_update_fragments(rxc, chunk_tsn);
512 
513     if (result == TRUE) rxc_bubbleup_ctsna(rxc);
514 
515     event_logi(VVERBOSE, "rxc_data_chunk_rx: after rxc_bubbleup_ctsna, rxc->ctsna=%u", rxc->ctsna);
516 
517     if (rxc->new_chunk_received == TRUE) {
518         if(se_recvDataChunk(se_chk, chunk_len, ad_idx) == SCTP_SUCCESS) {
519             /* resetting it */
520             rxc->new_chunk_received = FALSE;
521         }
522         /* else: ABORT has been sent and the association (possibly) removed in callback! */
523     }
524     return 1;
525 }
526 
527 /**
528  * Function triggered by flowcontrol, tells recvcontrol to
529  * send SACK to bundling using bu_put_SACK_Chunk() function.
530  * @return boolean to indicate, whether a SACK was generated, and should be sent !
531  */
rxc_create_sack(unsigned int * destination_address,boolean force_sack)532 boolean rxc_create_sack(unsigned int *destination_address, boolean force_sack)
533 {
534     rxc_buffer *rxc;
535     unsigned int num_of_frags;
536 
537     event_logii(VVERBOSE,
538                 "Entering rxc_create_sack(address==%u, force_sack==%s",
539                 ((destination_address != NULL) ? *destination_address : 0),
540                 ((force_sack == TRUE) ? "TRUE" : "FALSE"));
541 
542     rxc = (rxc_buffer *) mdi_readRX_control();
543     if (!rxc) {
544         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
545         return FALSE;
546     }
547 
548     if (rxc->contains_valid_sack == FALSE) {
549         event_log(INTERNAL_EVENT_0, "SACK structure was not updated (should have been)");
550         rxc_all_chunks_processed(FALSE);
551     }
552 
553     num_of_frags = g_list_length(rxc->frag_list);
554 
555     if (num_of_frags > 0)
556         rxc_send_sack_everytime();
557     else
558         rxc_send_sack_every_second_time();
559 
560     /* send sacks along every second time, generally */
561     /* some timers may want to have a SACK anyway */
562     /* first sack is sent at once, since datagrams_received==-1 */
563     if (force_sack == TRUE) {
564         rxc->lowest = rxc->ctsna;
565         bu_put_SACK_Chunk((SCTP_sack_chunk*)rxc->sack_chunk, destination_address);
566         return TRUE;
567     } else {
568 
569         /* in case we have not yet got any data, we will not want to send a SACK */
570         if (rxc->datagrams_received == -1)
571             return FALSE;
572 
573         if (rxc->datagrams_received % rxc->sack_flag != 0) {
574                 event_log(VVERBOSE, "Did not send SACK here - returning");
575                 return FALSE;
576         }
577         rxc->lowest = rxc->ctsna;
578         bu_put_SACK_Chunk((SCTP_sack_chunk*)rxc->sack_chunk,destination_address);
579         return TRUE;
580     }
581     return FALSE;
582 }
583 
584 
585 
586 /**
587  * the callback function when the sack timer goes off, and we must sack previously
588  * received data (e.g. after 200 msecs)
589  * Has three parameters as all timer callbacks
590  * @param   tid id of the timer that has gone off
591  * @param   assoc  pointer to the association this event belongs to
592  * @param   dummy  pointer that is not used here
593  */
rxc_sack_timer_cb(TimerID tid,void * assoc,void * dummy)594 void rxc_sack_timer_cb(TimerID tid, void *assoc, void *dummy)
595 {
596     unsigned short res;
597 
598     rxc_buffer *rxc;
599     event_log(INTERNAL_EVENT_1, "Timer Callback Function activated -> initiate sending of a SACK");
600     res = mdi_setAssociationData(*(unsigned int *) assoc);
601     if (res == 1)
602         error_log(ERROR_MAJOR, " association does not exist !");
603     if (res == 2) {
604         error_log(ERROR_MAJOR, "Association was not cleared..... !!!");
605         /* failure treatment ? */
606     }
607     /* all should be well now */
608     rxc = (rxc_buffer *) mdi_readRX_control();
609     if (!rxc) {
610         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
611         return;
612     }
613     rxc->timer_running = FALSE;
614     /* sending sack */
615     /* FIXME : maybe choose different address ??? */
616     rxc_create_sack(&rxc->last_address, TRUE);
617     bu_sendAllChunks(&rxc->last_address);
618 
619     mdi_clearAssociationData();
620     return;
621 }
622 
623 /**
624  * function called by bundling when a SACK is actually sent, to stop
625  * a possibly running  timer
626  */
rxc_stop_sack_timer(void)627 void rxc_stop_sack_timer(void)
628 {
629     rxc_buffer *rxc;
630     int result;
631 
632     rxc = (rxc_buffer *) mdi_readRX_control();
633     if (!rxc) {
634         error_log(ERROR_MINOR, "rxc_buffer instance not set !");
635         return;
636     }
637     /* also make sure you forget all the duplicates we received ! */
638     g_list_foreach(rxc->dup_list, &free_list_element, NULL);
639     g_list_free(rxc->dup_list);
640     rxc->dup_list = NULL;
641 
642     if (rxc->timer_running == TRUE) {
643         result = sctp_stopTimer(rxc->sack_timer);
644         event_logi(INTERNAL_EVENT_0, "Stopped Timer, Result was %d", result);
645         rxc->timer_running = FALSE;
646     }
647     return;
648 }
649 
rxc_sack_timer_is_running(void)650 boolean rxc_sack_timer_is_running(void)
651 {
652     rxc_buffer *rxc;
653     rxc = (rxc_buffer *) mdi_readRX_control();
654     if (!rxc) {
655         error_log(ERROR_MINOR, "rxc_buffer instance not set !");
656         return FALSE;
657     }
658     if (rxc->timer_running == TRUE) return TRUE;
659     return FALSE;
660 }
661 
662 /**
663  * called by bundling, after new data has been processed (so we may start building a sack chunk)
664  * or by streamengine, when ULP has read some data, and we want to update the RWND.
665  */
rxc_all_chunks_processed(boolean new_data_received)666 void rxc_all_chunks_processed(boolean new_data_received)
667 {
668     /* now go and create SACK structure from the array */
669     rxc_buffer *rxc=NULL;
670     SCTP_sack_chunk *sack=NULL;
671     unsigned short num_of_frags, num_of_dups;
672     unsigned short len16, count, frag_start16, frag_stop16;
673     unsigned int pos;
674     duplicate *dptr=NULL, d;
675     fragment32 *f32=NULL;
676     fragment chunk_frag;
677     GList *temp=NULL;
678     int bytesQueued = 0;
679     unsigned current_rwnd = 0;
680 
681     event_log(INTERNAL_EVENT_0, "Entering funtion rxc_all_chunks_processed ()");
682 
683     rxc = (rxc_buffer *) mdi_readRX_control();
684     if (!rxc) {
685         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
686         return;
687     }
688 
689     if (new_data_received == TRUE) rxc->datagrams_received++;
690 
691     num_of_frags = g_list_length(rxc->frag_list);
692     num_of_dups  = g_list_length(rxc->dup_list);
693 
694     /* limit size of SACK to 80 bytes plus fixed size chunk and chunk header */
695     /* FIXME : Limit number of Fragments/Duplicates according to ->PATH MTU<-  */
696     if (num_of_frags > 10) num_of_frags = 10;
697     if (num_of_dups > 10)  num_of_dups = 10;
698 
699     event_logii(VVERBOSE, "len of frag_list==%u, len of dup_list==%u", num_of_frags, num_of_dups);
700 
701     bytesQueued = se_getQueuedBytes();
702     if (bytesQueued < 0) bytesQueued = 0;
703     if ((unsigned int)bytesQueued > rxc->my_rwnd) {
704         current_rwnd = 0;
705     } else {
706         current_rwnd = rxc->my_rwnd - bytesQueued;
707     }
708     /* do SWS prevention */
709     if (current_rwnd > 0 && current_rwnd <= 2 * MAX_SCTP_PDU) current_rwnd = 1;
710 
711 
712     sack = (SCTP_sack_chunk*)rxc->sack_chunk;
713     sack->chunk_header.chunk_id = CHUNK_SACK;
714     sack->chunk_header.chunk_flags = 0;
715     len16 = sizeof(SCTP_chunk_header) + (2 + num_of_dups) * sizeof(unsigned int) +
716             (2 * num_of_frags + 2) * sizeof(unsigned short);
717 
718     sack->chunk_header.chunk_length = htons(len16);
719     sack->cumulative_tsn_ack = htonl(rxc->ctsna);
720     /* FIXME : deduct size of data still in queue, that is waiting to be picked up by an ULP */
721     sack->a_rwnd = htonl(current_rwnd);
722     sack->num_of_fragments  = htons(num_of_frags);
723     sack->num_of_duplicates = htons(num_of_dups);
724     pos = 0L;
725 
726     temp = g_list_first(rxc->frag_list); count = 0;
727     while ((temp != NULL) && (count < num_of_frags)) {
728 
729         f32 = (fragment32*)temp->data;
730 
731         event_logiii(VVERBOSE,"ctsna==%u, fragment.start==%u, fragment.stop==%u",
732                      rxc->ctsna, f32->start_tsn, f32->stop_tsn);
733 
734         if (((f32->start_tsn - rxc->ctsna) > 0xFFFF) || ((f32->stop_tsn - rxc->ctsna) > 0xFFFF)) {
735             error_log(ERROR_MINOR, "Fragment offset becomes too big");
736             break;
737         }
738         frag_start16 = (unsigned short) (f32->start_tsn - rxc->ctsna);
739         frag_stop16 = (unsigned short) (f32->stop_tsn - rxc->ctsna);
740         event_logii(VVERBOSE, "frag_start16==%u, frag_stop16==%u", frag_start16, frag_stop16);
741 
742         chunk_frag.start = htons((unsigned short)(f32->start_tsn - rxc->ctsna));
743         chunk_frag.stop = htons((unsigned short)(f32->stop_tsn - rxc->ctsna));
744         event_logii(VVERBOSE, "chunk_frag.start=%u,chunk_frag.stop ==%u",
745                                 ntohs(chunk_frag.start), ntohs(chunk_frag.stop));
746         memcpy(&sack->fragments_and_dups[pos], &chunk_frag, sizeof(fragment));
747         pos += sizeof(fragment);
748         temp = g_list_next(temp); count++;
749     }
750 
751     temp = g_list_first(rxc->dup_list); count = 0;
752     while ((temp != NULL) && (count < num_of_dups)) {
753         dptr = (duplicate*)temp->data;
754         if (dptr) d.duplicate_tsn = htonl(dptr->duplicate_tsn);
755         memcpy(&sack->fragments_and_dups[pos], &d, sizeof(duplicate));
756         pos += sizeof(duplicate);
757         temp = g_list_next(temp); count++;
758     }
759     /* start sack_timer set to 200 msecs */
760     if (rxc->timer_running != TRUE && new_data_received == TRUE) {
761         rxc->sack_timer = adl_startTimer(rxc->delay, &rxc_sack_timer_cb, TIMER_TYPE_SACK, &(rxc->my_association), NULL);
762         event_log(INTERNAL_EVENT_0, "Started SACK Timer !");
763         rxc->timer_running = TRUE;
764     }
765     rxc->contains_valid_sack = TRUE;
766     return;
767 }
768 
769 
770 /**
771   Function starts a SACK timer after data has been read by the ULP, and the
772   buffer is about to change...
773  */
rxc_start_sack_timer(unsigned int oldQueueLen)774 int rxc_start_sack_timer(unsigned int oldQueueLen)
775 {
776     rxc_buffer *rxc;
777     int bytesQueued = 0;
778 
779     rxc = (rxc_buffer *) mdi_readRX_control();
780     if (!rxc) {
781         error_log(ERROR_MINOR, "rxc_buffer instance not set - returning 0");
782         return (-1);
783     }
784 
785     bytesQueued = se_getQueuedBytes();
786     if (bytesQueued < 0) bytesQueued = 0;
787     /* no new data received, but we want updated SACK to be sent */
788     rxc_all_chunks_processed(FALSE);
789     if ((rxc->my_rwnd - oldQueueLen < 2 * MAX_SCTP_PDU) &&
790         (rxc->my_rwnd - bytesQueued >= 2 * MAX_SCTP_PDU)) {
791         /* send SACK at once */
792         rxc_create_sack(&rxc->last_address, TRUE);
793         bu_sendAllChunks(&rxc->last_address);
794         rxc_stop_sack_timer();
795     } else {    /* normal application read, no need to rush things */
796         if (rxc->timer_running != TRUE) {
797             rxc->sack_timer = adl_startTimer(rxc->delay, &rxc_sack_timer_cb, TIMER_TYPE_SACK, &(rxc->my_association), NULL);
798             event_log(INTERNAL_EVENT_0, "Started SACK Timer !");
799             rxc->timer_running = TRUE;
800         }
801     }
802     return 0;
803 }
804 
805 
806 /**
807   @return my current receiver window (32 bit unsigned value)
808  */
rxc_get_local_receiver_window(void)809 unsigned int rxc_get_local_receiver_window(void)
810 {
811     rxc_buffer *rxc;
812     rxc = (rxc_buffer *) mdi_readRX_control();
813     if (!rxc) {
814         error_log(ERROR_MINOR, "rxc_buffer instance not set - returning 0");
815         return (0);
816     }
817     event_logi(VERBOSE, "function rxc_get_my_receiver_window() returns %u", rxc->my_rwnd);
818     return rxc->my_rwnd;
819 }
820 
821 
822 /**
823   @return my current sack delay in msecs
824  */
rxc_get_sack_delay(void)825 int rxc_get_sack_delay(void)
826 {
827     rxc_buffer *rxc;
828     rxc = (rxc_buffer *) mdi_readRX_control();
829     if (!rxc) {
830         error_log(ERROR_MINOR, "rxc_buffer instance not set - returning default");
831         return (-1);
832     }
833     event_logi(VERBOSE, "function rxc_get_sack_delay() returns %u", rxc->delay);
834     return ((int)rxc->delay);
835 }
836 
837 /**
838   @return my current sack delay in msecs
839  */
rxc_set_sack_delay(unsigned int new_delay)840 int rxc_set_sack_delay(unsigned int new_delay)
841 {
842     rxc_buffer *rxc;
843     rxc = (rxc_buffer *) mdi_readRX_control();
844     if (!rxc) {
845         error_log(ERROR_MINOR, "rxc_buffer instance not set - returning default");
846         return (-1);
847     }
848     rxc->delay = new_delay;
849     event_logi(VERBOSE, "Setting new sack delay  to %u msecs", rxc->delay);
850     return 0;
851 }
852 
853 /**
854  Set the size of my receiver window. This needs to reflect buffer sizes.
855  Beware, this is really only a DUMMY function, too !
856  @param  new local receiver window (32 bit unsigned value)
857  @return 0 on success, else -1 on failure
858  */
rxc_set_local_receiver_window(unsigned int new_window)859 int rxc_set_local_receiver_window(unsigned int new_window)
860 {
861     rxc_buffer *rxc;
862     rxc = (rxc_buffer *) mdi_readRX_control();
863     if (!rxc) {
864         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
865         return (-1);
866     }
867     event_logi(VERBOSE, "function rxc_set_my_receiver_window(%u)", new_window);
868     rxc->my_rwnd = new_window;
869     return 0;
870 }
871 
872 
873 /**
874   Get the number of the current cumulative TSN, that we may ack
875   @return my current ctsna (32 bit unsigned value)
876  */
rxc_read_cummulativeTSNacked(void)877 unsigned int rxc_read_cummulativeTSNacked(void)
878 {
879     rxc_buffer *rxc;
880 
881     rxc = (rxc_buffer *) mdi_readRX_control();
882     if (!rxc) {
883         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
884         return (0);
885     }
886     return (rxc->ctsna);
887 }
888 
889 /**
890  * Helper function called, when we have gap reports in incoming
891  * SACK chunks....
892  */
rxc_send_sack_everytime(void)893 void rxc_send_sack_everytime(void)
894 {
895     rxc_buffer *rxc;
896 
897     rxc = (rxc_buffer *) mdi_readRX_control();
898     if (!rxc) {
899         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
900         return;
901     }
902     rxc->sack_flag = 1;
903 }
904 
905 /**
906  * Helper function called, when we have no gap reports in incoming
907  * SACK chunks....
908  */
rxc_send_sack_every_second_time(void)909 void rxc_send_sack_every_second_time(void)
910 {
911     rxc_buffer *rxc;
912 
913     rxc = (rxc_buffer *) mdi_readRX_control();
914     if (!rxc) {
915         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
916         return;
917     }
918     rxc->sack_flag = 2;
919 
920 }
921 
922 
923 /**
924  function only called in a restart case.
925  Beware : this has been largely untested !
926  @param  new_remote_TSN new tsn value of peer that has restarted
927  */
rxc_restart_receivecontrol(unsigned int my_rwnd,unsigned int new_remote_TSN)928 void rxc_restart_receivecontrol(unsigned int my_rwnd, unsigned int new_remote_TSN)
929 {
930     rxc_buffer *rxc;
931 
932     rxc = (rxc_buffer *) mdi_readRX_control();
933     if (!rxc) {
934         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
935         return;
936     }
937     rxc_stop_sack_timer();
938     g_list_foreach(rxc->frag_list, &free_list_element, NULL);
939     g_list_free(rxc->frag_list);
940     rxc->ctsna = new_remote_TSN - 1;
941     rxc->lowest = new_remote_TSN - 1;
942     rxc->highest = new_remote_TSN - 1;
943     /* initialize and set up lists */
944 
945     rxc->frag_list = NULL;
946     rxc->dup_list = NULL;
947     rxc->contains_valid_sack = FALSE;
948     rxc->timer_running = FALSE;
949     rxc->datagrams_received = -1;
950     rxc->sack_flag = 2;
951     rxc->last_address = 0;
952     rxc->my_rwnd = my_rwnd;
953     rxc->my_association = mdi_readAssociationID();
954     return;
955 }
956 
957 
rxc_process_forward_tsn(void * chunk)958 int rxc_process_forward_tsn(void* chunk)
959 {
960     rxc_buffer *rxc=NULL;
961     unsigned int fw_tsn;
962     unsigned int chunk_len;
963     unsigned int lo, hi;
964     fragment32 *frag=NULL;
965     GList *current = NULL;
966 
967     SCTP_forward_tsn_chunk* chk = (SCTP_forward_tsn_chunk*)chunk;
968 
969     fw_tsn = ntohl(chk->forward_tsn);
970     chunk_len = ntohs(chk->chunk_header.chunk_length);
971 
972     event_logii(INTERNAL_EVENT_0, "rxc_process_forward_tsn: %u, len:%u",fw_tsn, chunk_len);
973     rxc = (rxc_buffer *) mdi_readRX_control();
974     if (!rxc) {
975         error_log(ERROR_MAJOR, "rxc_buffer instance not set !");
976         return (-1);
977     }
978     /* discard old FORWARD_TSN */
979     if (after(rxc->ctsna, fw_tsn) || fw_tsn==rxc->ctsna || mdi_supportsPRSCTP() == FALSE) {
980         event_logii(VERBOSE, "rxc_process_forward_tsn --> discard fw_tsn !! (fw_tsn %u <= ctsna %u)",fw_tsn, rxc->ctsna);
981         return 0;
982     }
983 
984     current = g_list_first(rxc->frag_list);
985 
986     /* -get first fragment
987        -case1: fw_tsn after hi: delete fragment, continue with next fragment;
988        -case2: fw_tsn between hi and lo-1:
989                 delete fragment, set ctsna=hi, break;
990        -case3: fw_tsn before lo-1, set ctsna => fw_tsn, break;
991      */
992     while (current != NULL) {
993         frag = (fragment32*)current->data;
994         if (current != NULL && frag != NULL){
995             lo = frag->start_tsn;
996             hi = frag->stop_tsn;
997             if (before(fw_tsn, lo-1)) {
998                 /* case3: fw_tsn before lo-1, set ctsna => fw_tsn, break; */
999                 event_logi(VERBOSE, "process- case3: update ctsna to %u !",fw_tsn);
1000                 rxc->ctsna  = fw_tsn;
1001                 break;
1002             } else if (between(lo-1, fw_tsn, hi)) {
1003                 /* case2: fw_tsn between hi and lo-1: delete fragment, set ctsna=hi, break; */
1004                 rxc->frag_list = g_list_remove_link(rxc->frag_list, current);
1005                 g_list_free_1(current); free(frag);
1006                 event_logi(VERBOSE, "process- case2: remove fragment and update ctsna to %u !",hi);
1007                 rxc->ctsna = hi;
1008                 break;
1009             } else if (after(fw_tsn, hi)) {
1010                 /* case1: fw_tsn after hi: delete fragment, continue with next fragment; */
1011                 rxc->frag_list = g_list_remove_link(rxc->frag_list, current);
1012                 g_list_free_1(current); free(frag);
1013                 event_logi(VERBOSE, "process- case1: remove fragment, and set ctsna => %u !",hi);
1014                 rxc->ctsna = fw_tsn;
1015             } else {
1016                 error_log(ERROR_FATAL, "rxc_process_forward_tsn: impossible conditon");
1017                 abort();
1018             }
1019         }
1020         /* we are still here, take next fragment == first fragment */
1021         current = g_list_first(rxc->frag_list);
1022     }
1023     if (after(fw_tsn, rxc->ctsna)) {
1024         rxc->ctsna = fw_tsn;
1025         event_logi(VERBOSE, "rxc_process_forward_tsn: case4: set ctsna => %u !",fw_tsn);
1026     }
1027     se_deliver_unreliably(rxc->ctsna, chk);
1028 
1029     rxc_all_chunks_processed(TRUE);
1030 
1031     return 0;
1032 }
1033 
1034