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 "bundling.h"
45 #include "messages.h"
46 #include "recvctrl.h"
47 #include "reltransfer.h"
48 #include "errorhandler.h"
49 #include "streamengine.h"
50 #include "distribution.h"
51 
52 #include <stdio.h>
53 
54 #define TOTAL_SIZE(buf)		((buf)->ctrl_position+(buf)->sack_position+(buf)->data_position- 2*sizeof(SCTP_common_header))
55 
56 
57 
rbu_scanPDU(guchar * pdu,guint len)58 unsigned int rbu_scanPDU(guchar * pdu, guint len)
59 {
60     gushort processed_len = 0;
61     gushort chunk_len = 0;
62     unsigned int result = 0;
63     guchar *current_position;
64     guint pad_bytes;
65     SCTP_simple_chunk *chunk;
66 
67     current_position = pdu; /* points to the first chunk in this pdu */
68 
69     while (processed_len < len) {
70 
71         event_logii(VERBOSE, "rbu_scanPDU : len==%u, processed_len == %u", len, processed_len);
72 
73         chunk = (SCTP_simple_chunk *) current_position;
74         chunk_len = CHUNKP_LENGTH((SCTP_chunk_header *) chunk);
75 
76         if (chunk_len < 4 || chunk_len + processed_len > len) return result;
77 
78         if (chunk->chunk_header.chunk_id <= 30) {
79             result = result | (1 << chunk->chunk_header.chunk_id);
80             event_logii(VERBOSE, "rbu_scanPDU : Chunk type==%u, result == %x", chunk->chunk_header.chunk_id, result);
81         } else {
82             result = result | (1 << 31);
83             event_logii(VERBOSE, "rbu_scanPDU : Chunk type==%u setting bit 31 --> result == %x", chunk->chunk_header.chunk_id, result);
84         }
85         processed_len += chunk_len;
86         pad_bytes = ((processed_len % 4) == 0) ? 0 : (4 - processed_len % 4);
87         processed_len += pad_bytes;
88         chunk_len = (CHUNKP_LENGTH((SCTP_chunk_header *) chunk) + pad_bytes * sizeof(unsigned char));
89 
90         if (chunk_len < 4 || chunk_len + processed_len > len) return result;
91         current_position += chunk_len;
92 
93     }
94     return result;
95 }
96 
rbu_datagramContains(gushort chunk_type,unsigned int chunkArray)97 gboolean rbu_datagramContains(gushort chunk_type, unsigned int chunkArray)
98 {
99     unsigned int val = 0;
100 
101     if (chunk_type >= 31) {
102         val = (1 << 31);
103         if ((val & chunkArray) == 0) return FALSE;
104         else return TRUE;    /* meaning: it could be true */
105     }
106 
107     val = (1 << chunk_type);
108     if ((val & chunkArray) != 0) return TRUE;
109     else return FALSE;
110 
111 }
112 
113 
rbu_scanInitChunkForParameter(guchar * chunk,gushort paramType)114 guchar* rbu_scanInitChunkForParameter(guchar * chunk, gushort paramType)
115 {
116     gushort processed_len;
117     guint len = 0, parameterLength = 0;
118     guchar *current_position;
119     guint pad_bytes;
120     SCTP_init *initChunk;
121     SCTP_vlparam_header* vlp;
122 
123     initChunk = (SCTP_init *) chunk;
124 
125     if (initChunk->chunk_header.chunk_id != CHUNK_INIT &&
126         initChunk->chunk_header.chunk_id != CHUNK_INIT_ACK) {
127         return FALSE;
128     }
129     len = ntohs(initChunk->chunk_header.chunk_length);
130     current_position = initChunk->variableParams;
131     processed_len = (sizeof(SCTP_chunk_header)+sizeof(SCTP_init_fixed));
132 
133     while (processed_len < len) {
134         event_logii(INTERNAL_EVENT_0,
135                     "rbu_scanInitChunkForParameter : len==%u, processed_len == %u", len, processed_len);
136         vlp = (SCTP_vlparam_header*) current_position;
137         parameterLength = ntohs(vlp->param_length);
138 
139         if (parameterLength < 4 || parameterLength + processed_len > len) return NULL;
140 
141         if (ntohs(vlp->param_type) == paramType) {
142             return current_position;
143         }
144         processed_len += parameterLength;
145         pad_bytes = ((processed_len % 4) == 0) ? 0 : (4 - processed_len % 4);
146         processed_len += pad_bytes;
147         current_position += (parameterLength + pad_bytes * sizeof(unsigned char));
148     }
149     return NULL;
150 
151 }
152 
153 
154 /*
155  * rbu_findChunk: looks for chunk_type in a newly received datagram
156  *
157  * All chunks within the datagram are looked at, until one is found
158  * that equals the parameter chunk_type.
159  * @param  datagram     pointer to the newly received data
160  * @param  len          stop after this many bytes
161  * @param  chunk_type   chunk type to look for
162  * @return pointer to first chunk of chunk_type in SCTP datagram, else NULL
163  */
rbu_findChunk(guchar * datagram,guint len,gushort chunk_type)164 guchar* rbu_findChunk(guchar * datagram, guint len, gushort chunk_type)
165 {
166     gushort processed_len = 0, chunk_len = 0;
167     guchar *current_position;
168     guint pad_bytes;
169     SCTP_simple_chunk *chunk;
170 
171     current_position = datagram; /* points to the first chunk in this pdu */
172     while (processed_len < len) {
173 
174         event_logii(INTERNAL_EVENT_0,
175                     "rbu_findChunk : len==%u, processed_len == %u", len, processed_len);
176 
177         chunk = (SCTP_simple_chunk *) current_position;
178         if (chunk->chunk_header.chunk_id == chunk_type)
179             return current_position;
180         else {
181             chunk_len = CHUNKP_LENGTH((SCTP_chunk_header *) chunk);
182             if (chunk_len < 4 || chunk_len + processed_len > len) return NULL;
183 
184             processed_len += CHUNKP_LENGTH((SCTP_chunk_header *) chunk);
185             pad_bytes = ((processed_len % 4) == 0) ? 0 : (4 - processed_len % 4);
186             processed_len += pad_bytes;
187             chunk_len = (CHUNKP_LENGTH((SCTP_chunk_header *) chunk) + pad_bytes * sizeof(unsigned char));
188             if (chunk_len < 4 || chunk_len + processed_len > len) return NULL;
189             current_position += chunk_len;
190         }
191     }
192     return NULL;
193 }
194 
195 /*
196  * rbu_findAddress: looks for address type parameters in INIT or INIT-ACKs
197  * All parameters within the chunk are looked at, and the n-th supported address is
198  * copied into the provided buffer pointed to by the foundAddress parameter.
199  * If there are less than n addresses, an appropriate error is
200  * returned. n should be at least 1, of course.
201  * @param  chunk            pointer to an INIT or INIT ACK chunk
202  * @param  n                get the n-th address
203  * @param  foundAddress     pointer to a buffer where an address, if found, will be copied
204  * @return -1  for parameter problem, 0 for success (i.e. address found), 1 if there are not
205  *             that many addresses in the chunk.
206  */
rbu_findAddress(guchar * chunk,guint n,union sockunion * foundAddress,int supportedAddressTypes)207 gint rbu_findAddress(guchar * chunk, guint n, union sockunion* foundAddress, int supportedAddressTypes)
208 {
209     gushort processed_len;
210     guint len = 0, parameterLength = 0;
211     guchar *current_position;
212     guint pad_bytes;
213     SCTP_init *initChunk;
214     SCTP_vlparam_header* vlp;
215     SCTP_ip_address * address;
216     unsigned int foundAddressNumber = 0;
217 
218     initChunk = (SCTP_init *) chunk;
219     if (foundAddress == NULL || n < 1 || n > SCTP_MAX_NUM_ADDRESSES)
220         return -1;
221     if (initChunk->chunk_header.chunk_id != CHUNK_INIT &&
222         initChunk->chunk_header.chunk_id != CHUNK_INIT_ACK) {
223         return -1;
224     }
225     len = ntohs(initChunk->chunk_header.chunk_length);
226     current_position = initChunk->variableParams;
227     processed_len = (sizeof(SCTP_chunk_header)+sizeof(SCTP_init_fixed));
228 
229     while (processed_len < len) {
230         event_logii(INTERNAL_EVENT_0,
231                     "rbu_findAddress : len==%u, processed_len == %u", len, processed_len);
232         vlp = (SCTP_vlparam_header*) current_position;
233         parameterLength = ntohs(vlp->param_length);
234 
235         if (parameterLength < 4 || parameterLength + processed_len > len) return -1;
236 
237         if (ntohs(vlp->param_type) == VLPARAM_IPV4_ADDRESS &&
238             supportedAddressTypes & SUPPORT_ADDRESS_TYPE_IPV4) {
239             /* discard invalid addresses */
240             foundAddressNumber++;
241             if (foundAddressNumber == n) {
242                 address = (SCTP_ip_address *)current_position;
243                 /* copy the address over to the user buffer */
244                 foundAddress->sa.sa_family = AF_INET;
245                 foundAddress->sin.sin_port = 0;
246                 foundAddress->sin.sin_addr.s_addr = address->dest_addr.sctp_ipv4;
247                 return 0;
248             }
249 #ifdef HAVE_IPV6
250         } else if (ntohs(vlp->param_type) == VLPARAM_IPV6_ADDRESS &&
251             supportedAddressTypes & SUPPORT_ADDRESS_TYPE_IPV6) {
252             /* discard invalid addresses */
253             foundAddressNumber++;
254             if (foundAddressNumber == n) {
255                 address = (SCTP_ip_address *)current_position;
256                 /* copy the address over to the user buffer */
257                 foundAddress->sa.sa_family = AF_INET6;
258                 foundAddress->sin6.sin6_port = htons(0);
259                 foundAddress->sin6.sin6_flowinfo = htonl(0);
260 #ifdef HAVE_SIN6_SCOPE_ID
261                 foundAddress->sin6.sin6_scope_id = htonl(0);
262 #endif
263                 memcpy(foundAddress->sin6.sin6_addr.s6_addr,
264                        address->dest_addr.sctp_ipv6, sizeof(struct in6_addr));
265 
266                 return 0;
267             }
268 #endif
269         }
270         processed_len += parameterLength;
271         pad_bytes = ((processed_len % 4) == 0) ? 0 : (4 - processed_len % 4);
272         processed_len += pad_bytes;
273         current_position += (parameterLength + pad_bytes * sizeof(unsigned char));
274     }
275     return 1;
276 }
277 
278 /**
279  * looks for Error chunk_type in a newly received datagram
280  * that contains a special error cause code
281  *
282  * All chunks within the datagram are lookes at, until one is found
283  * that equals the parameter chunk_type.
284  * @param  datagram     pointer to the newly received data
285  * @param  len          stop after this many bytes
286  * @param  error_cause  error cause code to look for
287  * @return true is chunk_type exists in SCTP datagram, false if it is not in there
288  */
rbu_scanDatagramForError(guchar * datagram,guint len,gushort error_cause)289 gboolean rbu_scanDatagramForError(guchar * datagram, guint len, gushort error_cause)
290 {
291     gushort processed_len = 0, param_length = 0, chunk_length = 0;
292     gushort err_len = 0;
293 
294     guchar *current_position;
295     guint pad_bytes;
296     SCTP_simple_chunk *chunk;
297     SCTP_staleCookieError *err_chunk;
298 
299 
300     current_position = datagram; /* points to the first chunk in this pdu */
301     while (processed_len < len) {
302 
303         event_logii(VERBOSE,
304                     "rbu_scanDatagramForError : len==%u, processed_len == %u", len, processed_len);
305 
306         chunk = (SCTP_simple_chunk *) current_position;
307         chunk_length = CHUNKP_LENGTH((SCTP_chunk_header *) chunk);
308         if (chunk_length < 4 || chunk_length + processed_len > len) return FALSE;
309 
310         if (chunk->chunk_header.chunk_id == CHUNK_ERROR) {
311 
312             if (chunk_length < 4 || chunk_length + processed_len > len) return FALSE;
313 
314             event_log(INTERNAL_EVENT_0, "rbu_scanDatagramForError : Error Chunk Found");
315             /* now search for error parameter that fits */
316             while (err_len < chunk_length - sizeof(SCTP_chunk_header))  {
317                 err_chunk = (SCTP_staleCookieError *) &(chunk->simple_chunk_data[err_len]);
318                 if (ntohs(err_chunk->vlparam_header.param_type) == error_cause) {
319                     event_logi(VERBOSE,
320                                "rbu_scanDatagramForError : Error Cause %u found -> Returning TRUE",
321                                error_cause);
322                     return TRUE;
323                 }
324                 param_length = ntohs(err_chunk->vlparam_header.param_length);
325                 if (param_length < 4 || param_length + err_len > len) return FALSE;
326 
327                 err_len += param_length;
328                 while ((err_len % 4) != 0)
329                     err_len++;
330             }
331         }
332 
333         processed_len += chunk_length;
334         pad_bytes = ((processed_len % 4) == 0) ? 0 : (4 - processed_len % 4);
335         processed_len += pad_bytes;
336         chunk_length = (CHUNKP_LENGTH((SCTP_chunk_header *) chunk) + pad_bytes * sizeof(unsigned char));
337         if (chunk_length < 4 || chunk_length + processed_len > len) return FALSE;
338         current_position += chunk_length;
339     }
340     event_logi(VERBOSE,
341                "rbu_scanDatagramForError : Error Cause %u NOT found -> Returning FALSE",
342                error_cause);
343     return FALSE;
344 }
345 
346 
347 /**
348  * Disassembles chunks from a received datagram
349  *
350  * FIXME : data chunks may only be parsed after control chunks.....
351  *
352  * All chunks within the datagram are dispatched and sent to the appropriate
353  * module, i.e.: control chunks are sent to sctp_control/pathmanagement,
354  * SACK chunks to reliable_transfer, and data_chunks to RX_control.
355  * Those modules must get a pointer to the start of a chunk and
356  * information about its size (without padding).
357  * @param  address_index  index of address on which this data arrived
358  * @param  datagram     pointer to first chunk of the newly received data
359  * @param  len          length of payload (i.e. len of the concatenation of chunks)
360  */
rbu_rcvDatagram(guint address_index,guchar * datagram,guint len)361 gint rbu_rcvDatagram(guint address_index, guchar * datagram, guint len)
362 {
363     /* sctp common header header has been verified */
364     /* tag (if association is established) and CRC is okay */
365     /* get first chunk-id and length, pass pointers & len on to relevant module :
366        - CHUNK_INIT, CHUNK_INIT_ACK,CHUNK_ABORT, CHUNK_SHUTDOWN,CHUNK_SHUTDOWN_ACK
367        CHUNK_COOKIE_ECHO,CHUNK_COOKIE_ACK go to SCTP_CONTROL (change of association state)
368        - CHUNK_HBREQ, CHUNK_HBACK go to PATH_MAN instance
369        - CHUNK_SACK goes to RELIABLE_TRANSFER
370        - CHUNK_ERROR probably to SCTP_CONTROL as well  (at least there !)
371        - CHUNK_DATA goes to RX_CONTROL
372      */
373     guchar *current_position;
374     gushort processed_len = 0, chunk_len;
375     gushort pad_bytes;
376     SCTP_simple_chunk *chunk;
377     gboolean data_chunk_received = FALSE;
378 
379     int association_state = STATE_OK;
380     gboolean send_it = FALSE;
381 
382     bu_lock_sender();
383 
384     current_position = datagram; /* points to the first chunk in this pdu */
385     event_log(INTERNAL_EVENT_0, "Entered rbu_rcvDatagram()...... ");
386     /* CHECKME : beim Empfangen leerer Chunks tritt im Bundling eine Endlosschleife auf ??? */
387     while (processed_len < len) {
388 
389         chunk = (SCTP_simple_chunk *) current_position;
390         chunk_len = CHUNKP_LENGTH((SCTP_chunk_header *) chunk);
391         event_logiiii(INTERNAL_EVENT_0,
392                      "rbu_rcvDatagram(address=%u) : len==%u, processed_len = %u, chunk_len=%u",
393                      address_index, len, processed_len, chunk_len);
394         if ((processed_len+chunk_len) > len || chunk_len < 4) {
395             error_logiii(ERROR_MINOR, "Faulty chunklen=%u, total len=%u,processed_len=%u --> dropping packet  !",
396                                     chunk_len,len,processed_len);
397             /* if the association has already been removed, we cannot unlock it anymore */
398             bu_unlock_sender(&address_index);
399             return 1;
400         }
401         /*
402          * TODO :   Add return values to the chunk-functions, where they can indicate what
403          *          to do with the rest of the datagram (i.e. DISCARD after stale COOKIE_ECHO
404          *          with tie tags that do not match the current ones)
405          */
406         switch (chunk->chunk_header.chunk_id) {
407         case CHUNK_DATA:
408             event_log(INTERNAL_EVENT_0, "*******************  Bundling received DATA chunk");
409             rxc_data_chunk_rx((SCTP_data_chunk*) chunk, address_index);
410             data_chunk_received = TRUE;
411             break;
412         case CHUNK_INIT:
413             event_log(INTERNAL_EVENT_0, "*******************  Bundling received INIT chunk");
414             association_state = sctlr_init((SCTP_init *) chunk);
415             break;
416         case CHUNK_INIT_ACK:
417             event_log(INTERNAL_EVENT_0, "*******************  Bundling received INIT ACK chunk");
418             association_state = sctlr_initAck((SCTP_init *) chunk);
419             break;
420         case CHUNK_SACK:
421             event_log(INTERNAL_EVENT_0, "*******************  Bundling received SACK chunk");
422             rtx_process_sack(address_index, chunk, len);
423             break;
424         case CHUNK_HBREQ:
425             event_log(INTERNAL_EVENT_0, "*******************  Bundling received HB_REQ chunk");
426             pm_heartbeat((SCTP_heartbeat *) chunk, address_index);
427             break;
428         case CHUNK_HBACK:
429             event_log(INTERNAL_EVENT_0, "*******************  Bundling received HB_ACK chunk");
430             pm_heartbeatAck((SCTP_heartbeat *) chunk);
431             break;
432         case CHUNK_ABORT:
433             event_log(INTERNAL_EVENT_0, "*******************  Bundling received ABORT chunk");
434             association_state = sctlr_abort();
435             break;
436         case CHUNK_SHUTDOWN:
437             event_log(INTERNAL_EVENT_0, "*******************  Bundling received SHUTDOWN chunk");
438             association_state = sctlr_shutdown((SCTP_simple_chunk *) chunk);
439             break;
440         case CHUNK_SHUTDOWN_ACK:
441             event_log(INTERNAL_EVENT_0, "*******************  Bundling received SHUTDOWN ACK chunk");
442             association_state = sctlr_shutdownAck();
443             break;
444         case CHUNK_ERROR:
445             event_log(INTERNAL_EVENT_0, "Error Chunk");
446             eh_recv_chunk(chunk);
447             break;
448         case CHUNK_COOKIE_ECHO:
449             event_log(INTERNAL_EVENT_0, "*******************  Bundling received COOKIE ECHO chunk");
450             sctlr_cookie_echo((SCTP_cookie_echo *) chunk);
451             break;
452         case CHUNK_COOKIE_ACK:
453             event_log(INTERNAL_EVENT_0, "*******************  Bundling received COOKIE ACK chunk");
454             sctlr_cookieAck((SCTP_simple_chunk *) chunk);
455             break;
456      /* case CHUNK_ECNE:
457         case CHUNK_CWR:
458             event_logi(INTERNAL_EVENT_0,
459                        "Chunktype %u not Supported Yet !!!!!!!!", chunk->chunk_header.chunk_id);
460             break;*/
461         case CHUNK_SHUTDOWN_COMPLETE:
462             event_log(INTERNAL_EVENT_0, "*******************  Bundling received SHUTDOWN_COMPLETE chunk");
463             association_state = sctlr_shutdownComplete();
464             break;
465         case CHUNK_FORWARD_TSN:
466             if (mdi_supportsPRSCTP() == TRUE) {
467                 event_log(INTERNAL_EVENT_0, "*******************  Bundling received FORWARD_TSN chunk");
468                 rxc_process_forward_tsn((SCTP_simple_chunk *) chunk);
469                 break;
470             } else
471                 continue;
472     /*    case CHUNK_ASCONF: */
473             /* check that ASCONF chunks are standalone chunks, not bundled with any other
474                chunks. Else ignore the ASCONF chunk (but not the others) */
475 /*            event_log(INTERNAL_EVENT_0, "Bundling received ASCONF chunk");
476             asc_recv_asconf_chunk((SCTP_simple_chunk *) chunk);
477             break;
478         case CHUNK_ASCONF_ACK:
479             event_log(INTERNAL_EVENT_0, "Bundling received ASCONF_ACK chunk");
480             asc_recv_asconf_ack((SCTP_simple_chunk *) chunk);
481             break; */
482         default:
483         /* 00 - Stop processing this SCTP packet and discard it, do not process
484                 any further chunks within it.
485            01 - Stop processing this SCTP packet and discard it, do not process
486                 any further chunks within it, and report the unrecognized
487                 parameter in an 'Unrecognized Parameter Type' (in either an
488                 ERROR or in the INIT ACK).
489            10 - Skip this chunk and continue processing.
490            11 - Skip this chunk and continue processing, but report in an ERROR
491                 Chunk using the 'Unrecognized Chunk Type' cause of error. */
492             if ((chunk->chunk_header.chunk_id & 0xC0) == 0x0) {            /* 00 */
493                 processed_len = len;
494                 event_logi(EXTERNAL_EVENT_X, "00: Unknown chunktype %u in rbundling.c", chunk->chunk_header.chunk_id);
495             } else if ((chunk->chunk_header.chunk_id & 0xC0) == 0x40) {    /* 01 */
496                 processed_len = len;
497                 eh_send_unrecognized_chunktype((unsigned char*)chunk,chunk_len);
498                 event_logi(EXTERNAL_EVENT_X, "01: Unknown chunktype %u in rbundling.c",chunk->chunk_header.chunk_id);
499             } else if ((chunk->chunk_header.chunk_id & 0xC0) == 0x80) {    /* 10 */
500                 /* nothing */
501                 event_logi(EXTERNAL_EVENT_X, "10: Unknown chunktype %u in rbundling.c",chunk->chunk_header.chunk_id);
502             } else if ((chunk->chunk_header.chunk_id & 0xC0) == 0xC0) {    /* 11 */
503                 event_logi(EXTERNAL_EVENT_X, "11: Unknown chunktype %u in rbundling.c", chunk->chunk_header.chunk_id);
504                 eh_send_unrecognized_chunktype((unsigned char*)chunk,chunk_len);
505             }
506             break;
507         }
508 
509         processed_len += chunk_len;
510         pad_bytes = ((processed_len % 4) == 0) ? 0 : (4 - processed_len % 4);
511         processed_len += pad_bytes;
512         current_position += (chunk_len + pad_bytes) * sizeof(unsigned char);
513 
514         if (association_state != STATE_OK) processed_len = len;
515 
516         event_logiiii(VVERBOSE, "processed_len=%u, pad_bytes=%u, current_position=%u, chunk_len=%u",
517             processed_len, pad_bytes, current_position,chunk_len);
518     }
519 
520     if (association_state != STATE_STOP_PARSING_REMOVED) {
521 
522         if (data_chunk_received == TRUE) {
523             /* update SACK structure and start SACK timer */
524             rxc_all_chunks_processed(TRUE);
525         } else {
526             /* update SACK structure and datagram counter */
527             rxc_all_chunks_processed(FALSE);
528         }
529         /* optionally also add a SACK chunk, at least for every second datagram
530          * see section 6.2, second paragraph
531          */
532         if (data_chunk_received == TRUE){
533             send_it = rxc_create_sack(&address_index, FALSE);
534             se_doNotifications();
535             if (send_it==TRUE) bu_sendAllChunks(&address_index);
536         }
537         /* if the association has already been removed, we cannot unlock it anymore */
538         bu_unlock_sender(&address_index);
539     }
540 
541     return 0;
542 
543 }
544 
545 
546