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 #ifdef HAVE_CONpm_heartbeatFIG_H
45 #include <config.h>
46 #endif
47 
48 #include <errno.h>
49 
50 #include "sctp.h"
51 #include "globals.h"
52 #include "auxiliary.h"
53 #include "adaptation.h"
54 #include "chunkHandler.h"
55 #include "SCTP-control.h"
56 #include "pathmanagement.h"
57 #include "md5.h"
58 
59 
60 #define MAX_CHUNKS 8
61 
62 #ifndef IN_EXPERIMENTAL
63 #define  IN_EXPERIMENTAL(a)   ((((gint) (a)) & 0xf0000000) == 0xf0000000)
64 #endif
65 
66 #ifndef IN_BADCLASS
67 #define  IN_BADCLASS(a)    IN_EXPERIMENTAL((a))
68 #endif
69 
70 /* Other constants */
71 
72 
73 static unsigned short      writeCursor[MAX_CHUNKS];
74 static SCTP_simple_chunk*  chunks[MAX_CHUNKS];
75 static boolean             chunkCompleted[MAX_CHUNKS];
76 
77 static ChunkID freeChunkID = 0;
78 
79 void ch_addUnrecognizedParameter(unsigned char* pos, ChunkID cid,
80                                  unsigned short length, unsigned char* data);
81 
82 /******************************* internal functions ***********************************************/
83 /*
84  * computes a cookie signature.
85  * TODO: replace this by something safer than MD5
86  */
87 static int
signCookie(unsigned char * cookieString,unsigned short cookieLength,unsigned char * start_of_signature)88 signCookie(unsigned char *cookieString, unsigned short cookieLength,
89            unsigned char *start_of_signature)
90 {
91     int i;
92     MD5_CTX ctx;
93     SCTP_our_cookie *cookie;
94     unsigned char * key;
95 
96     if (cookieString == NULL)
97         return -1;
98     if (start_of_signature == NULL)
99         return -1;
100     if (cookieLength == 0)
101         return -1;
102     key =  key_operation(KEY_READ);
103     if (key == NULL)
104         return -1;
105 
106     cookie = (SCTP_our_cookie *) cookieString;
107     memset(cookie->hmac, 0, HMAC_LEN);
108 
109     MD5Init(&ctx);
110     MD5Update(&ctx, cookieString, cookieLength);
111     MD5Update(&ctx, key, SECRET_KEYSIZE);
112     MD5Final(start_of_signature, &ctx);
113 
114     event_log(INTERNAL_EVENT_0, "Computed MD5 signature : ");
115     for (i = 0; i < 4; i++) {
116         event_logiiii(VERBOSE, "%2.2x %2.2x %2.2x %2.2x",
117                       start_of_signature[i * 4], start_of_signature[i * 4 + 1],
118                       start_of_signature[i * 4 + 2], start_of_signature[i * 4 + 3]);
119     }
120 
121     return 0;
122 }
123 
124 
125 /**
126  * retrieveVLParamFromString scans for a parameter of a certain type in a message string.
127  * The message string must point to a parameter header. The function can also be used
128  * to find parameters within a parameter (e.g. addresses within a cookie).
129  * @param paramType type of paramter to scan for,
130  * @param mstring   pointer to the first parameter header, from which we start scanning
131  * @param length    maximum length of parameter field, that may be scanned.
132  * @return          position of first parameter occurence, relative to where mstring pointed to
133  *                  i.e. 0 returned, when mstring points to the parameter we scan for.
134  *                  OR -1 if not found !!!!!!!
135  */
retrieveVLParamFromString(guint16 paramType,guchar * mstring,guint16 length)136 static gint32 retrieveVLParamFromString(guint16 paramType, guchar * mstring, guint16 length)
137 {
138     guint16 curs;
139     guint16 pType;
140     SCTP_vlparam_header *param_header;
141 
142     curs = 0;
143 
144     /* TODO : add support for all Error Cause Codes ? ECC_XXXXXXXX */
145     while (curs < length) {
146         param_header = (SCTP_vlparam_header *) & mstring[curs];
147         pType = ntohs(param_header->param_type);
148 
149         if (ntohs(param_header->param_length) < 4) {
150             error_log(ERROR_MINOR, "Program/Peer implementation problem : parameter length 0");
151             return -1;
152         }
153 
154         if (pType == paramType) {
155             return curs;
156         }
157             else if (pType == VLPARAM_IPV4_ADDRESS ||
158                      pType == VLPARAM_IPV6_ADDRESS ||
159                      pType == VLPARAM_COOKIE ||
160                      pType == VLPARAM_COOKIE_PRESERV ||
161                      pType == ECC_STALE_COOKIE_ERROR ||
162                      pType == VLPARAM_SUPPORTED_ADDR_TYPES ||
163                      pType == VLPARAM_PRSCTP||
164                      pType == VLPARAM_SET_PRIMARY||
165                      pType == VLPARAM_ADAPTATION_LAYER_IND) {
166             curs += ntohs(param_header->param_length);
167             /* take care of padding */
168             while ((curs % 4) != 0)
169                 curs++;
170         } else if (pType == VLPARAM_ECN_CAPABLE || pType == VLPARAM_HOST_NAME_ADDR) {
171             event_logi(INTERNAL_EVENT_1, "parameter type %d not supported", pType);
172             curs += ntohs(param_header->param_length);
173             /* take care of padding here */
174             while ((curs % 4) != 0)
175                 curs++;
176         } else {
177             error_logi(ERROR_MINOR, "unknown parameter type %u in message", pType);
178             /* try to continue parsing */
179             if ((ntohs(param_header->param_length) + curs) <= length) {
180                 curs += ntohs(param_header->param_length);
181                 while ((curs % 4) != 0) curs++;
182             } else
183                 return -1;
184             /* take care of padding here */
185             while ((curs % 4) != 0)
186                 curs++;
187         }
188     }
189     return -1;
190 }
191 
192 
193 /**
194  * setIPAddresses finds all IP addresses in a message string.
195  * TODO : check for maximum number of addresses, there may possibly be an overflow
196  * @param   mstring     pointer to the beginning of the message string
197  * @param   length      maximum length of the message that is scanned for addresses
198  * @param   addresses   field in which we may return addresses
199  * @return  number of IPv4 addresses found
200 */
201 static gint32
setIPAddresses(unsigned char * mstring,guint16 length,union sockunion addresses[],unsigned int * peerTypes,unsigned int myTypes,union sockunion * lastSource,gboolean ignore_dups,gboolean ignoreLast)202 setIPAddresses(unsigned char *mstring, guint16 length, union sockunion addresses[],
203                 unsigned int* peerTypes, unsigned int myTypes, union sockunion* lastSource,
204                 gboolean ignore_dups, gboolean ignoreLast)
205 {
206     gint32 cursabs = 0;
207     gint32 cursrel = 0;
208     union sockunion tmpAddr;
209     SCTP_ip_address *address;
210     int nAddresses = 0, v4found = 0, idx;
211 #ifdef HAVE_IPV6
212     int v6found = 0;
213     union sockunion tmp_su;
214     AddressScopingFlags filterFlags;
215     gboolean localHostFound=FALSE, linkLocalFound = FALSE, siteLocalFound = FALSE;
216 #endif
217     gboolean discard = FALSE, last_found = FALSE, new_found;
218 
219     event_logii(VERBOSE, "setIPAddresses : length = %u, my supp. AddrTypes=%d", length, myTypes);
220 
221     (*peerTypes) = 0;
222     if (myTypes & SUPPORT_ADDRESS_TYPE_IPV4) {
223 
224         while ((cursrel = retrieveVLParamFromString(VLPARAM_IPV4_ADDRESS,
225                                                     &mstring[cursabs],
226                                                     (guint16)(length - cursabs)) ) >= 0) {
227 
228             address = (SCTP_ip_address *) & mstring[cursabs + cursrel];
229 
230             if (IS_IPV4_ADDRESS_PTR_NBO(address)) {
231                 discard  = FALSE;
232                 /* FIXME : either NBO or HBO -- do not mix these */
233                 if (IN_CLASSD(ntohl(address->dest_addr.sctp_ipv4))) discard = TRUE;
234                 if (IN_EXPERIMENTAL(ntohl(address->dest_addr.sctp_ipv4))) discard = TRUE;
235                 if (IN_BADCLASS(ntohl(address->dest_addr.sctp_ipv4))) discard = TRUE;
236                 if (INADDR_ANY == ntohl(address->dest_addr.sctp_ipv4)) discard = TRUE;
237                 if (INADDR_BROADCAST == ntohl(address->dest_addr.sctp_ipv4)) discard = TRUE;
238                 /*
239                 if (INADDR_LOOPBACK == ntohl(address->dest_addr.sctp_ipv4)) discard = TRUE;
240                 */
241                 event_logii(VVERBOSE, "Got IPv4 address %x, discard: %s !",
242                                         ntohl(address->dest_addr.sctp_ipv4), (discard==TRUE)?"TRUE":"FALSE");
243                 if(nAddresses >= MAX_NUM_ADDRESSES) {
244                    error_log(ERROR_MINOR, "Too many addresses found during IPv4 reading");
245                    discard = TRUE;
246                 }
247 
248                 if (discard == FALSE) {
249                     new_found = TRUE;
250                     tmpAddr.sa.sa_family = AF_INET;
251                     tmpAddr.sin.sin_port = 0;
252                     tmpAddr.sin.sin_addr.s_addr = address->dest_addr.sctp_ipv4;
253 
254                     if (ignore_dups == TRUE) {
255                         for (idx = 0; idx < v4found; idx++)
256                              if (adl_equal_address(&tmpAddr, &addresses[idx]) == TRUE) new_found = FALSE;
257                     }
258 
259                     if (new_found == TRUE) {
260                         addresses[v4found].sa.sa_family = AF_INET;
261                         addresses[v4found].sin.sin_port = 0;
262                         addresses[v4found].sin.sin_addr.s_addr = address->dest_addr.sctp_ipv4;
263                         nAddresses++; v4found++;
264                         (*peerTypes) |= SUPPORT_ADDRESS_TYPE_IPV4;
265                         event_logi(VERBOSE, "Found NEW IPv4 Address = %x", ntohl(address->dest_addr.sctp_ipv4));
266                     } else {
267                         event_log(VERBOSE, "IPv4 was in the INIT or INIT ACK chunk more than once");
268                     }
269                 }
270             } else {
271                 error_log(ERROR_MAJOR, "parameter problem, abort scanning in setIPAddresses");
272                 break;
273             }
274             cursabs += cursrel;
275             cursabs += 8;
276             if (cursabs >= length) break;
277         }   /* end : while */
278         event_logi(VERBOSE, "Found %u NEW IPv4 Addresses - now starting to look for IPv6", v4found);
279 
280     } /* end: myTypes & SUPPORT_ADDRESS_TYPE_IPV4 */
281 
282 #ifdef HAVE_IPV6
283     if (myTypes & SUPPORT_ADDRESS_TYPE_IPV6) {
284         /* and scan again from the very beginning................. */
285         cursabs = 0;
286         cursrel = 0;
287 
288         localHostFound = mdi_addressListContainsLocalhost(1, lastSource);
289         linkLocalFound = !( adl_filterInetAddress(lastSource, flag_HideLinkLocal));
290         siteLocalFound = !( adl_filterInetAddress(lastSource, flag_HideSiteLocal));
291 
292         if (localHostFound == FALSE) {
293             /* this is from a normal address, get all except loopback */
294             if (linkLocalFound) {
295                 filterFlags = (AddressScopingFlags)(flag_Default|flag_HideLoopback);
296             } else if (siteLocalFound) {
297                 filterFlags = (AddressScopingFlags)(flag_Default|flag_HideLinkLocal|flag_HideLoopback);
298             } else {
299                 filterFlags = (AddressScopingFlags)(flag_Default|flag_HideLocal);
300             }
301         } else  /* if localHostFound == TRUE) */ {
302              /* this is from a loopback, get all */
303              filterFlags = flag_Default;
304         }
305         event_logiii(VERBOSE, "localHostFound: %d,  linkLocalFound: %d, siteLocalFound: %d",
306                localHostFound, linkLocalFound,  siteLocalFound);
307 
308         while ((cursrel =
309                 retrieveVLParamFromString(VLPARAM_IPV6_ADDRESS, &mstring[cursabs],
310                                           length - cursabs)) >= 0) {
311             address = (SCTP_ip_address *) & mstring[cursabs + cursrel];
312 
313             if (IS_IPV6_ADDRESS_PTR_NBO(address)) {
314                 discard  = FALSE;
315                 tmp_su.sin6.sin6_family = AF_INET6;
316 #ifdef SIN6_LEN
317                 tmp_su.sin6.sin6_len = sizeof(struct sockaddr_in6);
318 #endif                          /* SIN6_LEN */
319                 memcpy(&(tmp_su.sin6.sin6_addr.s6_addr),&(address->dest_addr.sctp_ipv6), 16);
320                 /* Bugfix: just copy 16 bytes of the address, not sizeof(struct sockaddr_in6)! */
321 
322 #if defined (LINUX)
323                 if (IN6_IS_ADDR_UNSPECIFIED(&(address->dest_addr.sctp_ipv6))) discard = TRUE;
324                 if (IN6_IS_ADDR_MULTICAST(&(address->dest_addr.sctp_ipv6))) discard = TRUE;
325                 if (IN6_IS_ADDR_V4COMPAT(&(address->dest_addr.sctp_ipv6))) discard = TRUE;
326 #else
327                 if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr*)&(address->dest_addr.sctp_ipv6))) discard = TRUE;
328                 if (IN6_IS_ADDR_MULTICAST((struct in6_addr*)&(address->dest_addr.sctp_ipv6))) discard = TRUE;
329                 if (IN6_IS_ADDR_V4COMPAT((struct in6_addr*)&(address->dest_addr))) discard = TRUE;
330 #endif
331                 if (adl_filterInetAddress(&tmp_su, filterFlags) == FALSE) {
332                    discard = TRUE;
333                 }
334                 if(nAddresses >= MAX_NUM_ADDRESSES) {
335                    error_log(ERROR_MINOR, "Too many addresses found during IPv6 reading");
336                    discard = TRUE;
337                 }
338                 event_logiii(VERBOSE, "Found IPv6 Address - discard=%s - #v4=%d - #v6=%d !",
339                              (discard==TRUE)?"TRUE":"FALSE", v4found, v6found);
340                 if (discard == FALSE) {
341                     new_found = TRUE;
342 
343                     if (ignore_dups == TRUE) {
344                         for (idx = v4found; idx < v4found+v6found; idx++)
345                             if (adl_equal_address(&tmp_su, &addresses[idx]) == TRUE) {
346                                 new_found = FALSE;
347 #if defined (LINUX)
348                                 event_logiiiiiiii(VERBOSE, "Found OLD IPv6 Address %x:%x:%x:%x:%x:%x:%x:%x!",
349                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[0]),
350                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[1]),
351                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[2]),
352                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[3]),
353                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[4]),
354                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[5]),
355                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[6]),
356                                                   ntohs(tmp_su.sin6.sin6_addr.s6_addr16[7]));
357 #endif
358                             }
359                     }
360 
361                     if (new_found == TRUE) {
362                         addresses[nAddresses].sa.sa_family = AF_INET6;
363                         addresses[nAddresses].sin6.sin6_port = htons(0);
364                         addresses[nAddresses].sin6.sin6_flowinfo = htonl(0);
365 #ifdef HAVE_SIN6_SCOPE_ID
366                         addresses[nAddresses].sin6.sin6_scope_id = htonl(0);
367 #endif
368 
369                         memcpy(addresses[nAddresses].sin6.sin6_addr.s6_addr,
370                                address->dest_addr.sctp_ipv6, sizeof(struct in6_addr));
371                         nAddresses++; v6found++;
372                         (*peerTypes) |= SUPPORT_ADDRESS_TYPE_IPV6;
373 #if defined (LINUX)
374                         event_logiiiiiiii(VERBOSE, "Found NEW IPv6 Address %x:%x:%x:%x:%x:%x:%x:%x!",
375                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[0]),
376                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[1]),
377                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[2]),
378                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[3]),
379                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[4]),
380                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[5]),
381                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[6]),
382                                           ntohs(tmp_su.sin6.sin6_addr.s6_addr16[7]));
383 #endif
384 
385                     }
386                 }
387             } else {
388                 error_log(ERROR_MAJOR, "parameter problem, abort scanning in setIPAddresses");
389                 break;
390             }
391             cursabs += cursrel;
392             cursabs += 20;
393             if (cursabs >= length)
394                 break;
395         }
396 
397     }
398 #endif  /* HAVE_IPV6 */
399 
400     if (ignoreLast == FALSE) {
401         for (idx = 0; idx < nAddresses; idx++)
402             if (adl_equal_address(lastSource, &addresses[idx]) == TRUE) last_found = TRUE;
403 
404         if (last_found == FALSE) {
405             memcpy(&addresses[nAddresses], lastSource, sizeof(union sockunion));
406             event_log(VERBOSE, "Added also lastFromAddress to the addresslist !");
407             switch(sockunion_family(lastSource)) {
408                 case AF_INET : (*peerTypes) |= SUPPORT_ADDRESS_TYPE_IPV4; break;
409 #ifdef HAVE_IPV6
410                 case AF_INET6 : (*peerTypes) |= SUPPORT_ADDRESS_TYPE_IPV6; break;
411 #endif
412                 default: break;
413             }
414             nAddresses++;
415         }
416     }
417     return nAddresses;
418 }
419 
420 
enterChunk(SCTP_simple_chunk * chunk,const char * log_text)421 static void enterChunk(SCTP_simple_chunk * chunk, const char *log_text)
422 {
423     unsigned int cid;
424 
425     freeChunkID = (freeChunkID + 1) % MAX_CHUNKS;
426 
427     cid = freeChunkID;
428     event_logi(INTERNAL_EVENT_0, log_text, cid);
429 
430     chunks[freeChunkID] = chunk;
431     writeCursor[freeChunkID] = 0;
432     chunkCompleted[freeChunkID] = FALSE;
433 }
434 
435 /******************************* external functions ***********************************************/
436 
437 /*****  create, write into and read from init and initAck ******************************************/
438 
439 /* ch_makeInit makes an init and initializes the the fixed part of init */
ch_makeInit(unsigned int initTag,unsigned int rwnd,unsigned short noOutStreams,unsigned short noInStreams,unsigned int initialTSN)440 ChunkID ch_makeInit(unsigned int initTag, unsigned int rwnd, unsigned short noOutStreams,
441                     unsigned short noInStreams, unsigned int initialTSN)
442 {
443     SCTP_init *initChunk;
444 
445     /* creat init chunk */
446     initChunk = (SCTP_init *) malloc(sizeof(SCTP_init));
447 
448     if (initChunk == NULL) error_log_sys(ERROR_FATAL, (short)errno);
449 
450     memset(initChunk, 0, sizeof(SCTP_init));
451 
452 
453     /* enter fixed part of init */
454     initChunk->chunk_header.chunk_id = CHUNK_INIT;
455     initChunk->chunk_header.chunk_flags = 0x00;
456     initChunk->chunk_header.chunk_length = sizeof(SCTP_chunk_header) + sizeof(SCTP_init_fixed);
457     initChunk->init_fixed.init_tag = htonl(initTag);
458     initChunk->init_fixed.rwnd = htonl(rwnd);
459     initChunk->init_fixed.outbound_streams = htons(noOutStreams);
460     initChunk->init_fixed.inbound_streams = htons(noInStreams);
461     initChunk->init_fixed.initial_tsn = htonl(initialTSN);
462 
463     enterChunk((SCTP_simple_chunk *) initChunk, "created init %u ");
464 
465     return freeChunkID;
466 }
467 
468 
469 
470 /* ch_makeInitAck makes an initAck and initializes the the fixed part of initAck */
471 ChunkID
ch_makeInitAck(unsigned int initTag,unsigned int rwnd,unsigned short noOutStreams,unsigned short noInStreams,unsigned int initialTSN)472 ch_makeInitAck(unsigned int initTag,
473                unsigned int rwnd,
474                unsigned short noOutStreams, unsigned short noInStreams, unsigned int initialTSN)
475 {
476     SCTP_init *initAckChunk = NULL;
477 
478     /* creat init chunk */
479     initAckChunk = (SCTP_init *) malloc(sizeof(SCTP_init));
480     if (initAckChunk == NULL)
481         error_log_sys(ERROR_FATAL, (short)errno);
482 
483     memset(initAckChunk, 0, sizeof(SCTP_init));
484 
485     /* enter fixed part of init */
486     initAckChunk->chunk_header.chunk_id = CHUNK_INIT_ACK;
487     initAckChunk->chunk_header.chunk_flags = 0x00;
488     initAckChunk->chunk_header.chunk_length = sizeof(SCTP_chunk_header) + sizeof(SCTP_init_fixed);
489     initAckChunk->init_fixed.init_tag = htonl(initTag);
490     initAckChunk->init_fixed.rwnd = htonl(rwnd);
491     initAckChunk->init_fixed.outbound_streams = htons(noOutStreams);
492     initAckChunk->init_fixed.inbound_streams = htons(noInStreams);
493     initAckChunk->init_fixed.initial_tsn = htonl(initialTSN);
494 
495     enterChunk((SCTP_simple_chunk *) initAckChunk, "created initAckChunk %u ");
496 
497     return freeChunkID;
498 }
499 
500 
501 
502 
503 void
ch_enterSupportedAddressTypes(ChunkID chunkID,gboolean with_ipv4,gboolean with_ipv6,gboolean with_dns)504 ch_enterSupportedAddressTypes(ChunkID chunkID,
505                               gboolean with_ipv4, gboolean with_ipv6, gboolean with_dns)
506 {
507     SCTP_supported_addresstypes *param = NULL;
508     guint16 num_of_types = 0, position = 0;
509     guint16 total_length = 0;
510 
511     if (chunks[chunkID] == NULL) {
512         error_log(ERROR_MAJOR, "Invalid chunk ID");
513     }
514 
515     if (chunkCompleted[chunkID]) {
516         error_log(ERROR_MAJOR, " ch_enterSupportedAddressTypes : chunk already completed");
517         return;
518     }
519 
520     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
521         if (with_ipv4) num_of_types++ ;
522         if (with_ipv6) num_of_types++;
523         if (with_dns)  num_of_types++;
524 
525         /* append the new parameter */
526         param = (SCTP_supported_addresstypes *) & ((SCTP_init *)
527                                      chunks[chunkID])->variableParams[writeCursor[chunkID]];
528         /* _might_ be overflow here, at some time... */
529         if (num_of_types == 0)
530             error_log(ERROR_FATAL, " No Supported Address Types -- Program Error");
531 
532         total_length = sizeof(SCTP_vlparam_header) + num_of_types * sizeof(guint16);
533 
534         writeCursor[chunkID] += total_length;
535         if ((total_length % 4) != 0)
536             writeCursor[chunkID] += 2;
537 
538         /* enter cookie preservative */
539         param->vlparam_header.param_type = htons(VLPARAM_SUPPORTED_ADDR_TYPES);
540         param->vlparam_header.param_length = htons(total_length);
541         if (with_ipv4) {
542             param->address_type[position] = htons(VLPARAM_IPV4_ADDRESS);
543             position++;
544         }
545         if (with_ipv6) {
546             param->address_type[position] = htons(VLPARAM_IPV6_ADDRESS);
547             position++;
548         }
549         if (with_dns) {
550             param->address_type[position] = htons(VLPARAM_HOST_NAME_ADDR);
551             position++;
552         }
553         /* take care of padding */
554         if (position == 1 || position == 3)
555             param->address_type[position] = htons(0);
556 
557     } else {
558         error_log(ERROR_MAJOR, "ch_enterSupportedAddressTypes : chunk type not init");
559     }
560 }
561 
562 
563 /**
564  * ch_enterCookiePreservative appends a cookie preservative with the suggested
565  * cookie lifespan to an init chunk.
566  */
ch_enterCookiePreservative(ChunkID chunkID,unsigned int lifespanIncrement)567 void ch_enterCookiePreservative(ChunkID chunkID, unsigned int lifespanIncrement)
568 {
569     SCTP_cookie_preservative *preserv;
570     gint32 vl_param_curs;
571     guint16 vl_param_total_length;
572 
573     if (chunks[chunkID] == NULL) {
574         error_log(ERROR_MAJOR, "Invalid chunk ID");
575 
576     }
577 
578     if (chunkCompleted[chunkID]) {
579         error_log(ERROR_MAJOR, "ch_enterCookiePreservative : chunk already completed");
580         return;
581     }
582 
583     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
584         /* check if init chunk already contains a cookie preserv. */
585         vl_param_total_length =
586             ((SCTP_init *) chunks[chunkID])->chunk_header.chunk_length -
587             sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
588 
589         vl_param_curs = retrieveVLParamFromString(VLPARAM_COOKIE_PRESERV, &((SCTP_init *)
590                                                                             chunks
591                                                                             [chunkID])->
592                                                   variableParams[0], vl_param_total_length);
593         if (vl_param_curs >= 0) {
594             /* simply overwrite this cookie preserv. */
595             preserv = (SCTP_cookie_preservative *) & ((SCTP_init *)
596                                                       chunks[chunkID])->variableParams
597                 [vl_param_curs];
598         } else {
599             /* append the new parameter */
600             preserv = (SCTP_cookie_preservative *) & ((SCTP_init *)
601                                  chunks[chunkID])->variableParams[writeCursor[chunkID]];
602             /* _might_ be overflow here, at some time... */
603             writeCursor[chunkID] += sizeof(SCTP_cookie_preservative);
604         }
605 
606         /* enter cookie preservative */
607         preserv->vlparam_header.param_type = htons(VLPARAM_COOKIE_PRESERV);
608         preserv->vlparam_header.param_length = htons(sizeof(SCTP_cookie_preservative));
609         preserv->cookieLifetimeInc = htonl(lifespanIncrement);
610 
611     } else {
612         error_log(ERROR_MAJOR, "ch_enterCookiePreservative: chunk type not init");
613     }
614 }
615 
616 
617 
618 /**
619  *  ch_enterIPaddresses appends local IP addresses to a chunk, usually an init or initAck
620  */
ch_enterIPaddresses(ChunkID chunkID,union sockunion sock_addresses[],int noOfAddresses)621 int ch_enterIPaddresses(ChunkID chunkID, union sockunion sock_addresses[], int noOfAddresses)
622 {
623     unsigned char *mstring;
624     int i,length;
625     SCTP_ip_address *address;
626 
627     if (chunks[chunkID] == NULL) {
628         error_log(ERROR_MAJOR, "Invalid chunk ID");
629         return -1;
630     }
631 
632     if (chunkCompleted[chunkID]) {
633         error_log(ERROR_MAJOR, "ch_enterIPaddresses: chunk already completed");
634         return 1;
635     }
636 
637     length = 0;
638 
639     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
640         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
641 
642         mstring = &((SCTP_init *) chunks[chunkID])->variableParams[writeCursor[chunkID]];
643     } else {
644         mstring = &((SCTP_asconf*)chunks[chunkID])->variableParams[writeCursor[chunkID]];
645     }
646 
647     for (i = 0; i < noOfAddresses; i++) {
648 
649         address = (SCTP_ip_address *) & mstring[length];
650 
651         switch (sockunion_family(&(sock_addresses[i]))) {
652             case AF_INET:
653                 address->vlparam_header.param_type = htons(VLPARAM_IPV4_ADDRESS);
654                 address->vlparam_header.param_length = htons(8);
655                 address->dest_addr.sctp_ipv4 = sock2ip(&(sock_addresses[i]));
656                 length += 8;
657                 break;
658 #ifdef HAVE_IPV6
659             case AF_INET6:
660                 address->vlparam_header.param_type = htons(VLPARAM_IPV6_ADDRESS);
661                 address->vlparam_header.param_length = htons(20);
662                 memcpy(address->dest_addr.sctp_ipv6,
663                        &(sock2ip6(&(sock_addresses[i]))), sizeof(struct in6_addr));
664                 length += 20;
665                 break;
666 #endif
667             default:
668                 error_logi(ERROR_MAJOR, "Unsupported Address Family %d",
669                            sockunion_family(&(sock_addresses[i])));
670                 break;
671 
672         }   /* switch */
673     }       /* for */
674     writeCursor[chunkID] += length;
675 
676     return 0;
677 }
678 
ch_enterECNchunk(ChunkID initAckID,ChunkID initCID)679 int ch_enterECNchunk(ChunkID initAckID, ChunkID initCID)
680 {
681     return 0;
682 }
683 
ch_getPRSCTPfromCookie(ChunkID cookieCID)684 gboolean ch_getPRSCTPfromCookie(ChunkID cookieCID)
685 {
686     gboolean result = FALSE;
687     SCTP_vlparam_header *vl_Ptr = NULL;
688     guint16 curs;
689     guint16 pType;
690     guint16 pLen;
691     guint16 vlp_totalLength;
692     unsigned char* the_string=NULL;
693 
694    if (chunks[cookieCID] == NULL) {
695         error_log(ERROR_FATAL, "Invalid Cookie chunk ID");
696         return FALSE;
697     }
698     vlp_totalLength =
699             ((SCTP_cookie_echo *) chunks[cookieCID])->chunk_header.chunk_length -
700             COOKIE_FIXED_LENGTH - sizeof(SCTP_chunk_header);
701 
702     curs = 0;
703     the_string =  &((SCTP_cookie_echo *)chunks[cookieCID])->vlparams[0];
704 
705     while (curs < vlp_totalLength) {
706         vl_Ptr = (SCTP_vlparam_header *) & the_string[curs];
707         pType =  ntohs(vl_Ptr->param_type);
708         pLen  =  ntohs(vl_Ptr->param_length);
709         event_logiii(VERBOSE, "Scan variable parameters in cookie: Got type %u, len: %u, position %u",pType, pLen, curs);
710 
711         /* peer error - ignore - should send an error notification */
712         if (pLen < 4) return FALSE;
713 
714         if (pType == VLPARAM_PRSCTP) {
715             /* ha, we got one ! */
716 
717             if (pLen >= 4){
718                  event_log(VERBOSE, "Peer Supports PRSCTP");
719                  result = TRUE; /* peer supports it  */
720             }
721             break;
722         }
723         curs += pLen;
724         while ((curs % 4) != 0) curs++;
725     }
726     return result;
727 }
728 
729 
ch_getPRSCTPfromInitAck(ChunkID initAckCID)730 gboolean ch_getPRSCTPfromInitAck(ChunkID initAckCID)
731 {
732     gboolean result = FALSE;
733     SCTP_vlparam_header *vl_Ptr = NULL;
734     guint16 curs;
735     guint16 pType;
736     guint16 pLen;
737     guint16 vlp_totalLength;
738     unsigned char* ack_string;
739 
740    if (chunks[initAckCID] == NULL) {
741         error_log(ERROR_FATAL, "Invalid initAck chunk ID");
742         return -1;
743     }
744     vlp_totalLength = ((SCTP_init *)chunks[initAckCID])->chunk_header.chunk_length -
745                         sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
746 
747     event_logi(VERBOSE, "Scan initAckChunk for PRSCTP parameter: len %u", vlp_totalLength);
748 
749     curs = 0;
750     ack_string =  &((SCTP_init *)chunks[initAckCID])->variableParams[0];
751 
752     while (curs < vlp_totalLength) {
753         vl_Ptr = (SCTP_vlparam_header *) & ack_string[curs];
754         pType =  ntohs(vl_Ptr->param_type);
755         pLen  =  ntohs(vl_Ptr->param_length);
756 
757         if (pLen < 4) return  FALSE; /* peer error - ignore - should send an error notification */
758 
759         event_logiii(VERBOSE, "Scan variable parameters: Got type %u, len: %u, position %u",pType, pLen, curs);
760 
761         if (pType == VLPARAM_PRSCTP) {
762             /* ha, we got one ! */
763 
764             if (pLen >= 4) result = TRUE; /* peer supports it */
765             break;
766         }
767         curs += pLen;
768         while ((curs % 4) != 0) curs++;
769     }
770     return result;
771 }
772 
ch_enterPRSCTPfromInit(ChunkID initAckCID,ChunkID initCID)773 int ch_enterPRSCTPfromInit(ChunkID initAckCID, ChunkID initCID)
774 {
775     int result = -1;
776     SCTP_vlparam_header *vl_initPtr = NULL;
777     guint16 curs;
778     guint16 pType;
779     guint16 pLen;
780     guint16 vlp_totalLength;
781     unsigned char* init_string;
782     unsigned char* ack_string;
783 
784    if (chunks[initCID] == NULL || chunks[initAckCID] == NULL) {
785         error_log(ERROR_FATAL, "Invalid init or initAck chunk ID");
786         return -1;
787     }
788     vlp_totalLength = ((SCTP_init *)chunks[initCID])->chunk_header.chunk_length -
789                         sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
790 
791     event_logi(VERBOSE, "Scan initChunk for PRSCTP parameter: len %u", vlp_totalLength);
792 
793     curs = 0;
794     init_string =  &((SCTP_init *)chunks[initCID])->variableParams[0];
795 
796     while (curs < vlp_totalLength) {
797         ack_string =  &((SCTP_init *)chunks[initAckCID])->variableParams[writeCursor[initAckCID]];
798         vl_initPtr = (SCTP_vlparam_header *) & init_string[curs];
799         pType =  ntohs(vl_initPtr->param_type);
800         pLen  =  ntohs(vl_initPtr->param_length);
801 
802         if (pLen < 4) return -1; /* peer error - ignore - should send an error notification */
803 
804         event_logiii(VERBOSE, "Scan variable parameters: Got type %u, len: %u, position %u",pType, pLen, curs);
805 
806         if (pType == VLPARAM_PRSCTP) {
807             /* ha, we got one ! */
808 
809             if (pLen == 4) result = 0; /* peer supports it, but doesn't send anything unreliably  */
810             if (pLen > 4)  result = 1; /* peer supports it, and does send some */
811             memcpy(ack_string, vl_initPtr, pLen);
812             writeCursor[initAckCID] += pLen;
813         }
814         curs += pLen;
815         while ((curs % 4) != 0) curs++;
816     }
817     return result;
818 }
819 
ch_enterADDIP(ChunkID initAckID,ChunkID initCID)820 int ch_enterADDIP(ChunkID initAckID, ChunkID initCID)
821 {
822     return 0;
823 }
824 
825 
826 
ch_enterSetPrimary(ChunkID initAckID,ChunkID initCID)827 int ch_enterSetPrimary(ChunkID initAckID, ChunkID initCID)
828 {
829     return 0;
830 
831 }
832 
833 
834 
835 /* ch_enterCookieVLP adds the variable length cookie param to an initAck */
836 int
ch_enterCookieVLP(ChunkID initCID,ChunkID initAckID,SCTP_init_fixed * init_fixed,SCTP_init_fixed * initAck_fixed,guint32 cookieLifetime,guint32 local_tie_tag,guint32 peer_tie_tag,union sockunion local_Addresses[],guint16 num_local_Addresses,union sockunion peer_Addresses[],guint16 num_peer_Addresses)837 ch_enterCookieVLP(ChunkID initCID, ChunkID initAckID,
838                   SCTP_init_fixed * init_fixed,
839                   SCTP_init_fixed * initAck_fixed,
840                   guint32 cookieLifetime,
841                   guint32 local_tie_tag,
842                   guint32 peer_tie_tag,
843                   union sockunion local_Addresses[],
844                   guint16 num_local_Addresses,
845                   union sockunion peer_Addresses[], guint16 num_peer_Addresses)
846 {
847     SCTP_cookie_param *cookie;
848     unsigned short wCurs;
849     int result, count;
850     guint16 no_local_ipv4_addresses = 0;
851     guint16 no_remote_ipv4_addresses = 0;
852     guint16 no_local_ipv6_addresses = 0;
853     guint16 no_remote_ipv6_addresses = 0;
854 
855     if (chunks[initAckID] == NULL) {
856         error_log(ERROR_MAJOR, "Invalid chunk ID");
857         return -1;
858     }
859 
860     if (chunks[initAckID]->chunk_header.chunk_id == CHUNK_INIT_ACK) {
861         if (chunkCompleted[initAckID]) {
862             error_log(ERROR_MAJOR, "ch_enterCookieVLP: chunk already completed");
863             return -1;
864         }
865 
866         /* enter fixed length params into cookie (which is variable part of initAck) */
867         cookie = (SCTP_cookie_param *)
868             & ((SCTP_init *) chunks[initAckID])->variableParams[writeCursor[initAckID]];
869         cookie->vlparam_header.param_type = htons(VLPARAM_COOKIE);
870 
871         /* these contain the CURRENT tags ! */
872         cookie->ck.z_side_initAck = *initAck_fixed;
873         cookie->ck.a_side_init = *init_fixed;
874 
875         cookie->ck.local_tie_tag = htonl(local_tie_tag);
876         cookie->ck.peer_tie_tag  = htonl(peer_tie_tag);
877 
878         cookie->ck.src_port = mdi_readLastFromPort();
879         cookie->ck.dest_port = mdi_readLastDestPort();
880 
881         for (count = 0; count <  num_local_Addresses; count++) {
882             switch(sockunion_family(&(local_Addresses[count]))) {
883                 case AF_INET :
884                     no_local_ipv4_addresses++;
885 
886                     break;
887 #ifdef HAVE_IPV6
888                 case AF_INET6 :
889                     no_local_ipv6_addresses++;
890                     break;
891 #endif
892                 default :
893                     error_log(ERROR_MAJOR, "ch_enterCookieVLP: Address Type Error !");
894                     break;
895             }
896         }
897         for (count = 0; count <  num_peer_Addresses; count++) {
898             switch(sockunion_family(&(peer_Addresses[count]))) {
899                 case AF_INET :
900                     no_remote_ipv4_addresses++;
901 
902                     break;
903 #ifdef HAVE_IPV6
904                 case AF_INET6 :
905                     no_remote_ipv6_addresses++;
906                     break;
907 #endif
908                 default :
909                     error_log(ERROR_MAJOR, "ch_enterCookieVLP: Address Type Error !");
910                     break;
911             }
912 
913         }
914         cookie->ck.no_local_ipv4_addresses  = htons(no_local_ipv4_addresses);
915         cookie->ck.no_remote_ipv4_addresses = htons(no_remote_ipv4_addresses);
916 
917         /* TODO : IPv6 Fixes */
918 
919         cookie->ck.no_local_ipv6_addresses  = htons(no_local_ipv6_addresses);
920         cookie->ck.no_remote_ipv6_addresses = htons(no_remote_ipv6_addresses);
921 
922         wCurs = writeCursor[initAckID];
923 
924         writeCursor[initAckID] += sizeof(SCTP_cookie_param);
925 
926         event_logii(VERBOSE, "Building Cookie with %u local, %u peer addresses",
927                     num_local_Addresses, num_peer_Addresses);
928 
929         ch_enterIPaddresses(initAckID, local_Addresses, num_local_Addresses);
930         ch_enterIPaddresses(initAckID, peer_Addresses, num_peer_Addresses);
931 
932         /* add peers PRSCTP field to COOKIE parameter */
933         result = ch_enterPRSCTPfromInit(initAckID, initCID);
934 
935         /* check if endpoint is ADD-IP capable, store result, and put HIS chunk in cookie */
936         if (ch_enterADDIP(initAckID, initCID) > 0) {
937             /* check for set primary chunk ? Maybe add this only after Cookie Chunk ! */
938             ch_enterSetPrimary(initAckID, initCID);
939         }
940 
941         cookie->vlparam_header.param_length = htons((unsigned short)(writeCursor[initAckID] - wCurs));
942 
943         cookie->ck.sendingTime    = pm_getTime();
944         cookie->ck.cookieLifetime = cookieLifetime;
945 
946         cookie->ck.hmac[0] = 0;
947         cookie->ck.hmac[1] = 0;
948         cookie->ck.hmac[2] = 0;
949         cookie->ck.hmac[3] = 0;
950 
951         while ((writeCursor[initAckID] % 4) != 0) writeCursor[initAckID]++;
952 
953         signCookie((unsigned char *) &(cookie->ck.z_side_initAck),
954                             (unsigned short)(ntohs(cookie->vlparam_header.param_length) - 4), cookie->ck.hmac);
955 
956         ch_enterECNchunk(initAckID, initCID);
957         event_logi(VERBOSE, "ch_enterCookieVLP: PRSCTP support: %d", result);
958 
959         /* if both support PRSCTP, enter our PRSCTP parameter to INIT ACK chunk */
960         if ((result >= 0) && (mdi_supportsPRSCTP() == TRUE)){
961             ch_addParameterToInitChunk(initAckID, VLPARAM_PRSCTP, 0, NULL);
962         }
963 
964     } else {
965         error_log(ERROR_MAJOR, "ch_enterCookieVLP: chunk type not initAck");
966     }
967 
968     return 0;
969 }
970 
971 /*
972  * return -1 if we have to stop processing the data because of an unknown parameter
973  * and do not return anything to the peer.
974  * return 1 when we send back error, but stop chunk parsing
975  * return 0 if normal processing
976  */
ch_enterUnrecognizedParameters(ChunkID initCID,ChunkID AckCID,unsigned int supportedAddressTypes)977 int ch_enterUnrecognizedParameters(ChunkID initCID, ChunkID AckCID, unsigned int supportedAddressTypes)
978 {
979     SCTP_vlparam_header *vl_initPtr = NULL;
980     guint16 curs;
981     guint16 pType;
982     guint16 pLen;
983     guint16 vlp_totalLength;
984     gboolean with_ipv4=FALSE, with_ipv6=FALSE;
985     unsigned char* init_string;
986     unsigned char* ack_string;
987 
988     if (chunks[initCID] == NULL) {
989         error_log(ERROR_FATAL, "Invalid init chunk ID");
990         return -1;
991     }
992     if (chunks[AckCID] == NULL) {
993         error_log(ERROR_FATAL, "Invalid init ack chunk ID");
994         return -1;
995     }
996     /* scan init chunk for unrecognized parameters ! */
997     if ((supportedAddressTypes & SUPPORT_ADDRESS_TYPE_IPV4) == 0)
998         with_ipv4 = FALSE;
999     else
1000 
1001         with_ipv4 = TRUE;
1002 
1003     if ((supportedAddressTypes & SUPPORT_ADDRESS_TYPE_IPV6) == 0)
1004         with_ipv6 = FALSE;
1005     else
1006         with_ipv6 = TRUE;
1007 
1008     vlp_totalLength = ((SCTP_init *)chunks[initCID])->chunk_header.chunk_length -
1009                     sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
1010 
1011     event_logiii(VERBOSE, "Scan initk for Errors -- supported types = %u, IPv4: %s, IPv6: %s",
1012             supportedAddressTypes, (with_ipv4 == TRUE)?"TRUE":"FALSE", (with_ipv6 == TRUE)?"TRUE":"FALSE");
1013 
1014     curs = 0;
1015     init_string =  &((SCTP_init *)chunks[initCID])->variableParams[0];
1016 
1017     while (curs < vlp_totalLength) {
1018 
1019         ack_string =  &((SCTP_init *)chunks[AckCID])->variableParams[writeCursor[AckCID]];
1020         vl_initPtr = (SCTP_vlparam_header *) & init_string[curs];
1021         pType = ntohs(vl_initPtr->param_type);
1022         pLen  = ntohs(vl_initPtr->param_length);
1023 
1024         if (pLen < 4)  return -1;
1025 
1026         event_logiii(VERBOSE, "Scan variable parameters: type %u, len: %u, position %u",pType, pLen, curs);
1027 
1028         if (pType == VLPARAM_COOKIE_PRESERV ||
1029             pType == VLPARAM_SUPPORTED_ADDR_TYPES ||
1030             pType == VLPARAM_IPV4_ADDRESS ||
1031             pType == VLPARAM_IPV6_ADDRESS ||
1032             pType == VLPARAM_PRSCTP) {
1033 
1034             curs += pLen;
1035             /* take care of padding */
1036             while ((curs % 4) != 0) curs++;
1037         } else if (pType == VLPARAM_HOST_NAME_ADDR) {
1038             scu_abort(ECC_UNRESOLVABLE_ADDRESS, pLen, (unsigned char*)vl_initPtr);
1039             return -1;
1040         } else {
1041             event_logii(VERBOSE, "found unknown parameter type %u len %u in message", pType, pLen);
1042 
1043             if (STOP_PARAM_PROCESSING(pType)) return 1;
1044 
1045             if (STOP_PARAM_PROCESSING_WITH_ERROR(pType)){
1046 
1047                 ch_addUnrecognizedParameter(ack_string, AckCID, pLen, (unsigned char*)vl_initPtr);
1048                 return 1;
1049             }
1050             if (SKIP_PARAM_WITH_ERROR(pType)) {
1051                 ch_addUnrecognizedParameter(ack_string, AckCID, pLen, (unsigned char*)vl_initPtr);
1052             }
1053             /* finally: simple SKIP_PARAM ! */
1054             curs += pLen;
1055             /* take care of padding */
1056             while ((curs % 4) != 0) curs++;
1057 
1058         }
1059     }
1060     return 0;
1061 }
1062 
1063 /* ------------------------------------------------------------------------------------------------------*/
ch_enterUnrecognizedErrors(ChunkID initAckID,unsigned int supportedTypes,ChunkID * errorchunk,union sockunion * preferredDest,gboolean * destSet,gboolean * peerSupportsIPV4,gboolean * peerSupportsIPV6,gboolean * peerSupportsPRSCTP,gboolean * peerSupportsADDIP)1064 int ch_enterUnrecognizedErrors(ChunkID initAckID,
1065                                unsigned int supportedTypes,
1066                                ChunkID *errorchunk,
1067                                union sockunion* preferredDest,
1068                                gboolean* destSet,
1069                                gboolean* peerSupportsIPV4,
1070                                gboolean* peerSupportsIPV6,
1071                                gboolean* peerSupportsPRSCTP,
1072                                gboolean* peerSupportsADDIP)
1073 {
1074     SCTP_vlparam_header *vl_ackPtr = NULL;
1075     SCTP_vlparam_header *vl_optionsPtr = NULL;
1076     ChunkID cid = 0;
1077 
1078     guint16 curs;
1079     guint16 pType, oType;
1080     guint16 pLen;
1081     guint16 vlp_totalLength;
1082     gboolean with_ipv4 = FALSE, with_ipv6=FALSE;
1083     SCTP_ip_address* address = NULL;
1084     unsigned char* ack_string;
1085     int result;
1086 
1087     *peerSupportsPRSCTP = FALSE;
1088     *peerSupportsADDIP = FALSE;
1089 
1090     /* this is the default */
1091     *peerSupportsIPV4 = TRUE;
1092     *peerSupportsIPV6 = TRUE;
1093 
1094     if (chunks[initAckID] == NULL) {
1095         error_log(ERROR_FATAL, "Invalid init ack chunk ID");
1096     }
1097     if (errorchunk == NULL) {
1098         error_log(ERROR_FATAL, "Null pointer in ch_enterUnrecognizedErrors()");
1099     }
1100     *destSet = FALSE;
1101     /* scan init chunk for unrecognized parameters ! */
1102 
1103     if ((supportedTypes & SUPPORT_ADDRESS_TYPE_IPV4) == 0)
1104         with_ipv4 = FALSE;
1105     else
1106         with_ipv4 = TRUE;
1107 
1108     if ((supportedTypes & SUPPORT_ADDRESS_TYPE_IPV6) == 0)
1109         with_ipv6 = FALSE;
1110     else
1111         with_ipv6 = TRUE;
1112 
1113     event_logiii(VERBOSE, "Scan initAck for Errors supported types = %u, IPv4: %s, IPv6: %s",
1114             supportedTypes, (with_ipv4 == TRUE)?"TRUE":"FALSE", (with_ipv6 == TRUE)?"TRUE":"FALSE");
1115 
1116     vlp_totalLength = ((SCTP_init *)chunks[initAckID])->chunk_header.chunk_length -
1117                     sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
1118 
1119     curs = 0;
1120     ack_string =  &((SCTP_init *)chunks[initAckID])->variableParams[0];
1121 
1122     while (curs < vlp_totalLength) {
1123         vl_ackPtr = (SCTP_vlparam_header *) & ack_string[curs];
1124 
1125         pType = ntohs(vl_ackPtr->param_type);
1126         pLen =   ntohs(vl_ackPtr->param_length);
1127         event_logiii(VERBOSE, "Scan variable parameters: type %u, len: %u, position %u",pType, pLen, curs);
1128 
1129         if (pLen < 4) return -1;
1130 
1131         if (pType == VLPARAM_COOKIE_PRESERV || pType == VLPARAM_COOKIE ||
1132             pType == VLPARAM_SUPPORTED_ADDR_TYPES) {
1133 
1134             curs += pLen;
1135 
1136             /* take care of padding */
1137             while ((curs % 4) != 0) curs++;
1138 
1139         } else if (pType == VLPARAM_UNRECOGNIZED_PARAM) {
1140             vl_optionsPtr = (SCTP_vlparam_header *) & ack_string[curs+sizeof(SCTP_vlparam_header)];
1141             oType = ntohs(vl_optionsPtr->param_type);
1142 
1143             if (oType ==  VLPARAM_PRSCTP) {
1144                 *peerSupportsPRSCTP = FALSE;
1145                 curs += pLen;
1146                 /* take care of padding */
1147                 while ((curs % 4) != 0) curs++;
1148             } else if (oType ==  VLPARAM_ADDIP) {
1149                 *peerSupportsADDIP = FALSE;
1150                 curs += pLen;
1151                 /* take care of padding */
1152                 while ((curs % 4) != 0) curs++;
1153 
1154             } else if (oType == VLPARAM_IPV4_ADDRESS) {
1155                 *peerSupportsIPV4 = FALSE;
1156                 curs += pLen;
1157                 /* take care of padding */
1158                 while ((curs % 4) != 0) curs++;
1159             } else if (oType == VLPARAM_IPV6_ADDRESS) {
1160                 *peerSupportsIPV6 = FALSE;
1161                 curs += pLen;
1162                 /* take care of padding */
1163                 while ((curs % 4) != 0) curs++;
1164             } else { /* this is an unknown unknwon parameter....very strange...ignore it */
1165           /* this is probably a bakeoff test.... :-)   */
1166                 curs += pLen;
1167                 /* take care of padding */
1168                 while ((curs % 4) != 0) curs++;
1169                 event_logi(EXTERNAL_EVENT, "Encountered Unrecognized Param %u: stop parsing and return: stop !", oType);
1170             }
1171         } else if (pType == VLPARAM_IPV4_ADDRESS) {
1172             if (with_ipv4 != TRUE) {
1173                 if (cid == 0)
1174                     cid = ch_makeErrorChunk();
1175                 ch_enterErrorCauseData(cid, ECC_UNRESOLVABLE_ADDRESS,pLen,(unsigned char*)vl_ackPtr);
1176 
1177             }
1178             curs += pLen;
1179             /* take care of padding */
1180 
1181             while ((curs % 4) != 0) curs++;
1182         } else if (pType == VLPARAM_IPV6_ADDRESS) {
1183             if (with_ipv6 != TRUE) {
1184                 if (cid == 0)
1185                     cid = ch_makeErrorChunk();
1186                 ch_enterErrorCauseData(cid, ECC_UNRESOLVABLE_ADDRESS,pLen,(unsigned char*)vl_ackPtr);
1187 
1188             }
1189             curs += pLen;
1190             /* take care of padding */
1191             while ((curs % 4) != 0) curs++;
1192 
1193         } else if (pType == VLPARAM_SET_PRIMARY) {
1194             result = retrieveVLParamFromString(VLPARAM_IPV4_ADDRESS, (guchar*)vl_ackPtr, pLen);
1195             if (result < 0) {
1196 #ifdef HAVE_IPV6
1197                 result = retrieveVLParamFromString(VLPARAM_IPV6_ADDRESS, (guchar*)vl_ackPtr, pLen);
1198                 if (result < 0) {
1199                     if (cid == 0) cid = ch_makeErrorChunk();
1200                     ch_enterErrorCauseData(cid, ECC_UNRECOGNIZED_PARAMS, pLen,(unsigned char*)vl_ackPtr);
1201                     curs += pLen;
1202                     /* take care of padding */
1203                     while ((curs % 4) != 0) curs++;
1204                     continue;
1205                 } else {
1206                     event_logi(VERBOSE, "Found an IPv6 Address parameter at offset %i",result);
1207                     *destSet = TRUE;
1208                     /* we got an IPv6 address */
1209                     address = (SCTP_ip_address *) &ack_string[curs+sizeof(SCTP_vlparam_header)];
1210                     preferredDest->sa.sa_family = AF_INET6;
1211                     preferredDest->sin6.sin6_port = htons(0);
1212                     preferredDest->sin6.sin6_flowinfo = htonl(0);
1213 #ifdef HAVE_SIN6_SCOPE_ID
1214                     preferredDest->sin6.sin6_scope_id = htonl(0);
1215 #endif
1216                     memcpy(&preferredDest->sin6.sin6_addr.s6_addr,
1217                            address->dest_addr.sctp_ipv6, sizeof(struct in6_addr));
1218                     /* FIXME: check if we got the correct address ! */
1219                 }
1220 #else
1221                 if (cid == 0) cid = ch_makeErrorChunk();
1222                 ch_enterErrorCauseData(cid, ECC_UNRECOGNIZED_PARAMS, pLen,(unsigned char*)vl_ackPtr);
1223                 curs += pLen;
1224                 /* take care of padding */
1225                 while ((curs % 4) != 0) curs++;
1226                 continue;
1227 #endif
1228             } else {
1229                 *destSet = TRUE;
1230                 /* we got an IPv4 address */
1231                 address = (SCTP_ip_address *) &ack_string[curs+sizeof(SCTP_vlparam_header)];
1232                 preferredDest->sa.sa_family = AF_INET;
1233                 preferredDest->sin.sin_port = 0;
1234                 preferredDest->sin.sin_addr.s_addr = address->dest_addr.sctp_ipv4;
1235                 /* FIXME: check if we got the correct address ! */
1236             }
1237             curs += pLen;
1238             /* take care of padding */
1239             while ((curs % 4) != 0) curs++;
1240 
1241         } else if (pType == VLPARAM_PRSCTP) {
1242             event_log(EXTERNAL_EVENT, "found PRSCTP parameter - skipping it !");
1243             *peerSupportsPRSCTP = TRUE;
1244             curs += pLen;
1245             /* take care of padding */
1246             while ((curs % 4) != 0) curs++;
1247             continue;
1248         } else if (pType == VLPARAM_ADDIP) {
1249             event_log(EXTERNAL_EVENT, "found ADDIP parameter - skipping it !");
1250             *peerSupportsADDIP = TRUE;
1251             if (cid == 0) cid = ch_makeErrorChunk();
1252             ch_enterErrorCauseData(cid, ECC_UNRECOGNIZED_PARAMS, pLen,(unsigned char*)vl_ackPtr);
1253             curs += pLen;
1254             /* take care of padding */
1255             while ((curs % 4) != 0) curs++;
1256             continue;
1257         } else {
1258             event_logii(VERBOSE, "found unknown parameter type %u len %u in message",pType,pLen);
1259 
1260             if (STOP_PARAM_PROCESSING(pType)) {
1261                 *errorchunk = cid;
1262                 event_log(EXTERNAL_EVENT, "Encountered STOP Param: Stop Parsing and return !");
1263                 return -1;
1264             }
1265 
1266             if (STOP_PARAM_PROCESSING_WITH_ERROR(pType)){
1267                  if (cid == 0) cid = ch_makeErrorChunk();
1268                  ch_enterErrorCauseData(cid,VLPARAM_UNRECOGNIZED_PARAM ,pLen,(unsigned char*)vl_ackPtr);
1269                  *errorchunk = cid;
1270                  return 1;
1271             }
1272             if (SKIP_PARAM_WITH_ERROR(pType)) {
1273                 if (cid == 0) cid = ch_makeErrorChunk();
1274                 ch_enterErrorCauseData(cid,VLPARAM_UNRECOGNIZED_PARAM ,pLen,(unsigned char*)vl_ackPtr);
1275             }
1276             /* finally: simple SKIP_PARAM ! */
1277             curs += pLen;
1278             /* take care of padding */
1279             while ((curs % 4) != 0) curs++;
1280         }
1281     }
1282     *errorchunk = cid;
1283     event_logi(EXTERNAL_EVENT, "Processed InitAck Chunk: error chunk : %u", cid);
1284     return 0;
1285 }
1286 
1287 
1288 /* ch_initiateTag reads the initiate tag from an init or initAck */
ch_initiateTag(ChunkID chunkID)1289 unsigned int ch_initiateTag(ChunkID chunkID)
1290 {
1291     if (chunks[chunkID] == NULL) {
1292         error_log(ERROR_MAJOR, "Invalid chunk ID");
1293 
1294         return 0;
1295     }
1296 
1297     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1298         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1299         return ntohl(((SCTP_init *) chunks[chunkID])->init_fixed.init_tag);
1300     } else {
1301         error_log(ERROR_MAJOR, "ch_initiateTag: chunk type not init or initAck");
1302         return 0;
1303 
1304     }
1305 }
1306 
1307 
1308 
1309 /* ch_receiverWindow reads the remote receiver window from an init or initAck */
ch_receiverWindow(ChunkID chunkID)1310 unsigned int ch_receiverWindow(ChunkID chunkID)
1311 {
1312     if (chunks[chunkID] == NULL) {
1313         error_log(ERROR_MAJOR, "Invalid chunk ID");
1314         return 0;
1315     }
1316 
1317     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1318         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1319         return ntohl(((SCTP_init *) chunks[chunkID])->init_fixed.rwnd);
1320     } else {
1321         error_log(ERROR_MAJOR, "ch_receiverWindow: chunk type not init or initAck");
1322         return 0;
1323     }
1324 }
1325 
1326 
1327 
1328 /* ch_initialTSN reads the initial TSN from an init or initAck */
ch_initialTSN(ChunkID chunkID)1329 unsigned int ch_initialTSN(ChunkID chunkID)
1330 {
1331     if (chunks[chunkID] == NULL) {
1332         error_log(ERROR_MAJOR, "Invalid chunk ID");
1333         return 0;
1334     }
1335 
1336     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1337         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1338         return ntohl(((SCTP_init *) chunks[chunkID])->init_fixed.initial_tsn);
1339     } else {
1340         error_log(ERROR_MAJOR, "ch_initialTSN: chunk type not init or initAck");
1341         return 0;
1342     }
1343 }
1344 
1345 
1346 
1347 /* ch_noOutStreams reads the number of output streams from an init or initAck */
ch_noOutStreams(ChunkID chunkID)1348 unsigned short ch_noOutStreams(ChunkID chunkID)
1349 {
1350     if (chunks[chunkID] == NULL) {
1351         error_log(ERROR_MAJOR, "Invalid chunk ID");
1352         return 0;
1353     }
1354 
1355     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1356         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1357         return ntohs(((SCTP_init *) chunks[chunkID])->init_fixed.outbound_streams);
1358     } else {
1359         error_log(ERROR_MAJOR, "ch_noOutStreams: chunk type not init or initAck");
1360         return 0;
1361     }
1362 }
1363 
1364 
1365 
1366 /* ch_noInStreams reads the number of input streams from an init or initAck */
ch_noInStreams(ChunkID chunkID)1367 unsigned short ch_noInStreams(ChunkID chunkID)
1368 {
1369     if (chunks[chunkID] == NULL) {
1370         error_log(ERROR_MAJOR, "Invalid chunk ID");
1371         return 0;
1372     }
1373 
1374     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1375         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1376         return ntohs(((SCTP_init *) chunks[chunkID])->init_fixed.inbound_streams);
1377     } else {
1378         error_log(ERROR_MAJOR, "ch_noInStreams: chunk type not init or initAck");
1379         return 0;
1380     }
1381 }
1382 
1383 
1384 /**
1385  *  ch_cookieLifeTime returns the suggested cookie lifespan increment if a cookie
1386  *  preservative is present in a init chunk.
1387  */
ch_cookieLifeTime(ChunkID chunkID)1388 unsigned int ch_cookieLifeTime(ChunkID chunkID)
1389 {
1390     gint32 vl_param_curs;
1391     guint16 vl_param_total_length;
1392     SCTP_cookie_preservative *preserv;
1393 
1394 
1395     if (chunks[chunkID] == NULL) {
1396 
1397         error_log(ERROR_MAJOR, "Invalid chunk ID");
1398         return 0;
1399     }
1400 
1401     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1402         vl_param_total_length =
1403             ((SCTP_init *) chunks[chunkID])->chunk_header.chunk_length -
1404             sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
1405 
1406         vl_param_curs = retrieveVLParamFromString(VLPARAM_COOKIE_PRESERV, &((SCTP_init *)
1407                                                                             chunks
1408                                                                             [chunkID])->
1409                                                   variableParams[0], vl_param_total_length);
1410         if (vl_param_curs >= 0) {
1411             /* found cookie preservative */
1412             preserv = (SCTP_cookie_preservative *) & ((SCTP_init *)
1413                                                       chunks[chunkID])->variableParams[vl_param_curs];
1414             return (ntohl(preserv->cookieLifetimeInc) + sci_getCookieLifeTime());
1415         } else {
1416             return sci_getCookieLifeTime();
1417         }
1418     } else {
1419         error_log(ERROR_MAJOR, "ch_cookieLifeTime: chunk type not init");
1420         return 0;
1421     }
1422 }
1423 
1424 /**
1425  *  ch_getSupportedAddressTypes() processes a INIT or INIT-ACK chunk and
1426  *  returns a value that indicates, which address types are supported by the peer.
1427  */
ch_getSupportedAddressTypes(ChunkID chunkID)1428 unsigned int ch_getSupportedAddressTypes(ChunkID chunkID)
1429 {
1430     gint32 vl_param_curs;
1431     guint16 vl_param_total_length, pos=0, num=0, pLen = 0;
1432     SCTP_supported_addresstypes *param = NULL;
1433 
1434     guint32 result=0;
1435 
1436     if (chunks[chunkID] == NULL) {
1437         error_log(ERROR_MAJOR, "Invalid chunk ID");
1438         return 0;
1439     }
1440 
1441     if ((chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) ||
1442         (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK)) {
1443         vl_param_total_length =
1444             ((SCTP_init *) chunks[chunkID])->chunk_header.chunk_length -
1445             sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
1446 
1447         vl_param_curs = retrieveVLParamFromString(VLPARAM_SUPPORTED_ADDR_TYPES, &((SCTP_init *)
1448                                                   chunks[chunkID])->variableParams[0], vl_param_total_length);
1449 
1450         if (vl_param_curs >= 0) {
1451             /* found supported address types parameter */
1452             param = (SCTP_supported_addresstypes*)
1453                         &((SCTP_init *)chunks[chunkID])->variableParams[vl_param_curs];
1454 
1455             pLen = ntohs(param->vlparam_header.param_length);
1456 
1457             if (pLen < 4 || pLen > 12) return result;
1458 
1459             while(pos < pLen) {
1460                 if (ntohs(param->address_type[num]) == VLPARAM_IPV4_ADDRESS)
1461                     result |= SUPPORT_ADDRESS_TYPE_IPV4;
1462                 else if (ntohs(param->address_type[num]) == VLPARAM_IPV6_ADDRESS)
1463                     result |= SUPPORT_ADDRESS_TYPE_IPV6;
1464                 else if (ntohs(param->address_type[num]) == VLPARAM_HOST_NAME_ADDR)
1465                     result |= SUPPORT_ADDRESS_TYPE_DNS;
1466 
1467 
1468                 num++;
1469                 pos += sizeof(guint16);
1470             }
1471             return result;
1472         }
1473         return (SUPPORT_ADDRESS_TYPE_IPV4 | SUPPORT_ADDRESS_TYPE_IPV6 | SUPPORT_ADDRESS_TYPE_DNS);
1474     } else {
1475         error_log(ERROR_MAJOR, "ch_getSupportedAddressTypes(): Wrong chunk type !");
1476         return 0;
1477     }
1478 }
1479 
1480 
1481 
1482 /* ch_IPaddresses reads the IP-addresses from an init or initAck */
ch_IPaddresses(ChunkID chunkID,unsigned int mySupportedTypes,union sockunion addresses[],unsigned int * supportedTypes,union sockunion * lastSource)1483 int ch_IPaddresses(ChunkID chunkID, unsigned int mySupportedTypes, union sockunion addresses[],
1484                     unsigned int *supportedTypes, union sockunion* lastSource)
1485 {
1486     int noOfAddresses;
1487 
1488     short vl_param_total_length;
1489 
1490     if (chunks[chunkID] == NULL) {
1491         error_log(ERROR_MAJOR, "Invalid chunk ID");
1492         return 0;
1493     }
1494 
1495     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1496         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1497         vl_param_total_length =
1498             ((SCTP_init *) chunks[chunkID])->chunk_header.chunk_length -
1499             sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
1500 
1501         /* retrieve addresses from initAck */
1502         noOfAddresses = setIPAddresses(&((SCTP_init *)chunks[chunkID])->variableParams[0],
1503                                                       vl_param_total_length, addresses, supportedTypes,
1504                                                       mySupportedTypes, lastSource, TRUE, FALSE);
1505         event_logii(VERBOSE, "Found %d addresses in %s chunk !", noOfAddresses,
1506                     ((chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) ? "INIT" : "INIT ACK"));
1507 
1508         return noOfAddresses;
1509     } else {
1510         error_log(ERROR_MINOR, "ch_IPaddresses: chunk type not init or initAck");
1511         return 0;
1512     }
1513 }
1514 
1515 
1516 
1517 /*
1518  * ch_cookieParam reads the cookie variable length parameter from an initAck
1519  */
ch_cookieParam(ChunkID chunkID)1520 SCTP_cookie_param *ch_cookieParam(ChunkID chunkID)
1521 {
1522     short vl_param_curs;
1523     short vl_param_total_length;
1524 
1525     if (chunks[chunkID] == NULL) {
1526         error_log(ERROR_MAJOR, "Invalid chunk ID");
1527         return NULL;
1528     }
1529 
1530     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK) {
1531         vl_param_total_length =
1532             ((SCTP_init *) chunks[chunkID])->chunk_header.chunk_length -
1533             sizeof(SCTP_chunk_header) - sizeof(SCTP_init_fixed);
1534 
1535         vl_param_curs = retrieveVLParamFromString(VLPARAM_COOKIE,
1536                                                   &((SCTP_init *)chunks[chunkID])->variableParams[0],
1537                                                   vl_param_total_length);
1538         if (vl_param_curs >= 0) {
1539             /* found cookie */
1540             return (SCTP_cookie_param *) & ((SCTP_init *)chunks[chunkID])->variableParams[vl_param_curs];
1541         } else {
1542             /* ignore initAck message, init timer will abort */
1543             error_log(ERROR_MAJOR, "initAck without cookie received, message discarded");
1544             return NULL;
1545         }
1546     } else {
1547         error_log(ERROR_MINOR, "ch_cookieParam: chunk type not init or initAck");
1548         return NULL;
1549     }
1550 }
1551 
1552 
1553 
1554 /* ch_initFixed reads the fixed part of an init or initAck as complete structure */
ch_initFixed(ChunkID chunkID)1555 SCTP_init_fixed *ch_initFixed(ChunkID chunkID)
1556 {
1557     if (chunks[chunkID] == NULL) {
1558         error_log(ERROR_MAJOR, "Invalid chunk ID");
1559         return NULL;
1560     }
1561 
1562     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT_ACK ||
1563         chunks[chunkID]->chunk_header.chunk_id == CHUNK_INIT) {
1564         return &((SCTP_init *) chunks[chunkID])->init_fixed;
1565     } else {
1566         error_log(ERROR_MAJOR, "ch_noInStreams: chunk type not init or initAck");
1567         return NULL;
1568     }
1569 }
1570 
1571 
1572 
1573 /****** create and read from cookie chunk *********************************************************/
1574 
1575 /**
1576  * ch_makeCookie creates a cookie chunk.
1577  */
ch_makeCookie(SCTP_cookie_param * cookieParam)1578 ChunkID ch_makeCookie(SCTP_cookie_param * cookieParam)
1579 {
1580     SCTP_cookie_echo *cookieChunk;
1581 
1582     /* create cookie chunk */
1583     cookieChunk = (SCTP_cookie_echo *) malloc(sizeof(SCTP_cookie_echo));
1584 
1585     if (cookieChunk == NULL) {
1586         error_log(ERROR_MAJOR, "Malloc Failed in ch_makeCookie, returning -1 !");
1587         return -1;
1588     }
1589     if (cookieParam == NULL) {
1590         error_log(ERROR_MAJOR, "ch_makeCookie: NULL parameter passed (InitAck without Cookie ???");
1591         free(cookieChunk);
1592         return -1;
1593     }
1594 
1595     memset(cookieChunk, 0, sizeof(SCTP_cookie_echo));
1596 
1597     cookieChunk->chunk_header.chunk_id = CHUNK_COOKIE_ECHO;
1598     cookieChunk->chunk_header.chunk_flags = 0x00;
1599     cookieChunk->chunk_header.chunk_length = ntohs(cookieParam->vlparam_header.param_length);
1600 
1601     enterChunk((SCTP_simple_chunk *) cookieChunk, "created cookieChunk %u ");
1602 
1603 
1604     /*  copy cookie parameter EXcluding param-header into chunk            */
1605     /*  z_side_initAck is the first struct/data part in our cookie         */
1606 
1607     memcpy(&(cookieChunk->cookie), &(cookieParam->ck.z_side_initAck),
1608            ntohs(cookieParam->vlparam_header.param_length) - sizeof(SCTP_vlparam_header));
1609 
1610     while ((writeCursor[freeChunkID] % 4) != 0) writeCursor[freeChunkID]++;
1611 
1612     return freeChunkID;
1613 }
1614 
1615 
1616 /*
1617  * ch_cookieInitFixed creates an init chunk from the fixed part of an init contained in a cookie
1618  *  and returns its chunkID
1619  */
ch_cookieInitFixed(ChunkID chunkID)1620 ChunkID ch_cookieInitFixed(ChunkID chunkID)
1621 {
1622     SCTP_init *initChunk;
1623 
1624     if (chunks[chunkID] == NULL) {
1625         error_log(ERROR_MAJOR, "Invalid chunk ID");
1626         return 0;
1627     }
1628 
1629     /* creat init chunk from init data< in cookie */
1630     initChunk = (SCTP_init *) malloc(sizeof(SCTP_init));
1631     if (initChunk == NULL)
1632         error_log_sys(ERROR_FATAL, (short)errno);
1633 
1634     memset(initChunk, 0, sizeof(SCTP_init));
1635 
1636     /* enter fixed part of init */
1637     initChunk->chunk_header.chunk_id = CHUNK_INIT;
1638     initChunk->chunk_header.chunk_flags = 0x00;
1639     initChunk->chunk_header.chunk_length = sizeof(SCTP_chunk_header) + sizeof(SCTP_init_fixed);
1640     initChunk->init_fixed = ((SCTP_cookie_echo *) chunks[chunkID])->cookie.a_side_init;
1641 
1642     enterChunk((SCTP_simple_chunk *) initChunk, "created initChunk from cookie %u ");
1643 
1644     return freeChunkID;
1645 }
1646 
1647 
1648 
1649 /* ch_cookieInitAckFixed creates an initAck chunk from the fixed part of an initAck contained in a
1650    cookie and returns its chunkID */
ch_cookieInitAckFixed(ChunkID chunkID)1651 ChunkID ch_cookieInitAckFixed(ChunkID chunkID)
1652 {
1653     SCTP_init *initAckChunk;
1654 
1655     if (chunks[chunkID] == NULL) {
1656         error_log(ERROR_MAJOR, "Invalid chunk ID");
1657         return 0;
1658     }
1659 
1660     /* creat initAck chunk from init data in cookie */
1661     initAckChunk = (SCTP_init *) malloc(sizeof(SCTP_init));
1662     if (initAckChunk == NULL)
1663         error_log_sys(ERROR_FATAL, (short)errno);
1664 
1665     memset(initAckChunk, 0, sizeof(SCTP_init));
1666 
1667     /* enter fixed part of init */
1668     initAckChunk->chunk_header.chunk_id = CHUNK_INIT_ACK;
1669     initAckChunk->chunk_header.chunk_flags = 0x00;
1670     initAckChunk->chunk_header.chunk_length = sizeof(SCTP_chunk_header) + sizeof(SCTP_init_fixed);
1671     initAckChunk->init_fixed = ((SCTP_cookie_echo *) chunks[chunkID])->cookie.z_side_initAck;
1672 
1673     enterChunk((SCTP_simple_chunk *) initAckChunk, "created initAckChunk %u  from cookie");
1674 
1675     return freeChunkID;
1676 }
1677 
1678 
1679 
1680 /* ch_cookieIPaddresses reads the IP-addresses from a cookie */
ch_cookieIPDestAddresses(ChunkID chunkID,unsigned int mySupportedTypes,union sockunion addresses[],unsigned int * peerSupportedAddressTypes,union sockunion * lastSource)1681 int ch_cookieIPDestAddresses(ChunkID chunkID, unsigned int mySupportedTypes,
1682                              union sockunion addresses[],
1683                              unsigned int *peerSupportedAddressTypes,
1684                              union sockunion* lastSource)
1685 {
1686     int nAddresses;
1687     int vl_param_total_length;
1688     guint16 no_loc_ipv4_addresses, no_remote_ipv4_addresses;
1689     guint16 no_loc_ipv6_addresses, no_remote_ipv6_addresses;
1690 
1691     union sockunion temp_addresses[MAX_NUM_ADDRESSES];
1692 
1693     if (chunks[chunkID] == NULL) {
1694         error_log(ERROR_MAJOR, "Invalid chunk ID");
1695         return 0;
1696     }
1697 
1698     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1699         no_loc_ipv4_addresses =
1700             ntohs(((SCTP_cookie_echo *) chunks[chunkID])->cookie.no_local_ipv4_addresses);
1701         no_remote_ipv4_addresses =
1702             ntohs(((SCTP_cookie_echo *) chunks[chunkID])->cookie.no_remote_ipv4_addresses);
1703         no_loc_ipv6_addresses =
1704             ntohs(((SCTP_cookie_echo *) chunks[chunkID])->cookie.no_local_ipv6_addresses);
1705         no_remote_ipv6_addresses =
1706             ntohs(((SCTP_cookie_echo *) chunks[chunkID])->cookie.no_remote_ipv6_addresses);
1707 
1708         vl_param_total_length =
1709             ((SCTP_cookie_echo *) chunks[chunkID])->chunk_header.chunk_length -
1710             COOKIE_FIXED_LENGTH - sizeof(SCTP_chunk_header);
1711 
1712         event_logi(VVERBOSE, " Computed total length of vparams : %d", vl_param_total_length);
1713         event_logii(VVERBOSE, " Num of local/remote IPv4 addresses %u / %u",
1714                     no_loc_ipv4_addresses, no_remote_ipv4_addresses);
1715         event_logii(VVERBOSE, " Num of local/remote IPv6 addresses %u / %u",
1716                     no_loc_ipv6_addresses, no_remote_ipv6_addresses);
1717 
1718         /* retrieve destination addresses from cookie */
1719         /* TODO: FIX this    vl_param_total_length parameter, so that later addresses are not
1720            retrieved as well ! */
1721         nAddresses = setIPAddresses(&((SCTP_cookie_echo *)chunks[chunkID])->vlparams[0],
1722                                                    (guint16)vl_param_total_length, temp_addresses,
1723                                                    peerSupportedAddressTypes, mySupportedTypes,
1724                                                    lastSource, FALSE, TRUE);
1725         if (nAddresses !=
1726             no_loc_ipv4_addresses + no_remote_ipv4_addresses +
1727             no_loc_ipv6_addresses + no_remote_ipv6_addresses) {
1728             error_log(ERROR_FATAL, "Found more or less addresses than should be in the cookie !");
1729         }
1730 
1731         memcpy(addresses, &temp_addresses[no_loc_ipv4_addresses],
1732                no_remote_ipv4_addresses * sizeof(union sockunion));
1733 
1734         if (no_remote_ipv6_addresses != 0)
1735             memcpy(&addresses[no_remote_ipv4_addresses],
1736                    &temp_addresses[no_loc_ipv4_addresses +
1737                                    no_remote_ipv4_addresses +
1738                                    no_loc_ipv6_addresses],
1739                    no_remote_ipv6_addresses * sizeof(union sockunion));
1740 
1741 
1742         return (no_remote_ipv4_addresses+no_remote_ipv6_addresses);
1743     } else {
1744         error_log(ERROR_MAJOR, "ch_cookieIPaddresses: chunk type not cookie");
1745         return 0;
1746     }
1747 }
1748 
1749 
1750 
1751 /* ch_staleCookie checks if this is a stale cookie and returns 0 if not and lifetime
1752    in msecs if it is. */
ch_staleCookie(ChunkID chunkID)1753 unsigned int ch_staleCookie(ChunkID chunkID)
1754 {
1755     SCTP_cookie_echo *cookie_echo_chunk;
1756     SCTP_our_cookie *cookie_param;
1757     unsigned int lifetime;
1758 
1759     if (chunks[chunkID] == NULL) {
1760         error_log(ERROR_MAJOR, "Invalid chunk ID");
1761         return FALSE;
1762     }
1763 
1764     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1765         cookie_echo_chunk = (SCTP_cookie_echo *) chunks[chunkID];
1766         cookie_param = &(cookie_echo_chunk->cookie);
1767         lifetime = pm_getTime() - cookie_param->sendingTime;
1768         event_logi(INTERNAL_EVENT_0, "ch_staleCookie: lifetime = %u msecs", lifetime);
1769 
1770         if (lifetime > cookie_param->cookieLifetime) {
1771             return lifetime;
1772         } else
1773             return 0;
1774     } else {
1775         error_log(ERROR_MAJOR, "ch_staleCookie: chunk type not cookie");
1776         return FALSE;
1777     }
1778 }
1779 
1780 /**
1781  * function reads local tie tag from a received cookie echo chunk
1782  */
ch_CookieLocalTieTag(ChunkID chunkID)1783 guint32 ch_CookieLocalTieTag(ChunkID chunkID)
1784 {
1785 
1786     if (chunks[chunkID] == NULL) {
1787         error_log(ERROR_MAJOR, "Invalid chunk ID");
1788         return 0;
1789     }
1790 
1791     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1792         return (ntohl(((SCTP_cookie_echo *) chunks[chunkID])->cookie.local_tie_tag));
1793     } else {
1794         error_log(ERROR_MAJOR, "ch_CookieLocalTieTag : Not a CookieEcho chunk !");
1795         return 0;
1796     }
1797 }
1798 
1799 /**
1800  * function reads peer tie tag from a received cookie echo chunk
1801  */
ch_CookiePeerTieTag(ChunkID chunkID)1802 guint32 ch_CookiePeerTieTag(ChunkID chunkID)
1803 {
1804 
1805     if (chunks[chunkID] == NULL) {
1806         error_log(ERROR_MAJOR, "Invalid chunk ID");
1807         return 0;
1808     }
1809 
1810     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1811         return (ntohl(((SCTP_cookie_echo *) chunks[chunkID])->cookie.peer_tie_tag));
1812     } else {
1813         error_log(ERROR_MAJOR, "ch_CookiePeerTieTag : Not a CookieEcho chunk !");
1814         return 0;
1815     }
1816 }
1817 
1818 /**
1819  * function reads local port from a received cookie echo chunk
1820  */
ch_CookieSrcPort(ChunkID chunkID)1821 guint16 ch_CookieSrcPort(ChunkID chunkID)
1822 {
1823     if (chunks[chunkID] == NULL) {
1824         error_log(ERROR_MAJOR, "Invalid chunk ID");
1825         return 0;
1826     }
1827 
1828     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1829         return (ntohs(((SCTP_cookie_echo *) chunks[chunkID])->cookie.src_port));
1830     } else {
1831         error_log(ERROR_MAJOR, "ch_CookieLocalPort : Not a CookieEcho chunk !");
1832         return 0;
1833     }
1834 }
1835 
1836 /**
1837  * function reads local port from a received cookie echo chunk
1838  */
ch_CookieDestPort(ChunkID chunkID)1839 guint16 ch_CookieDestPort(ChunkID chunkID)
1840 {
1841     if (chunks[chunkID] == NULL) {
1842         error_log(ERROR_MAJOR, "Invalid chunk ID");
1843         return 0;
1844     }
1845 
1846     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1847         return (ntohs(((SCTP_cookie_echo *) chunks[chunkID])->cookie.dest_port));
1848     } else {
1849         error_log(ERROR_MAJOR, "ch_CookieLocalPort : Not a CookieEcho chunk !");
1850         return 0;
1851     }
1852 }
1853 
1854 
1855 
1856 /**
1857  *    check if this is a good cookie, i.e. verify HMAC signature
1858  *      @return TRUE when signature is correct, else false (-1,1)
1859  */
ch_goodCookie(ChunkID chunkID)1860 boolean ch_goodCookie(ChunkID chunkID)
1861 {
1862     SCTP_cookie_echo *cookie_chunk;
1863     SCTP_our_cookie *cookie;
1864     guchar cookieSignature[HMAC_LEN];
1865     guchar ourSignature[HMAC_LEN];
1866     guint16 chunklen;
1867     guint32 i;
1868 
1869     if (chunks[chunkID] == NULL) {
1870         error_log(ERROR_MAJOR, "Invalid chunk ID");
1871         return FALSE;
1872     }
1873 
1874     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_COOKIE_ECHO) {
1875         /* this is a bit messy -- should do some cleanups here */
1876         cookie_chunk = (SCTP_cookie_echo *) chunks[chunkID];
1877         cookie = &(cookie_chunk->cookie);
1878         /* store HMAC */
1879         memcpy(cookieSignature, cookie->hmac, HMAC_LEN);
1880 
1881         chunklen = cookie_chunk->chunk_header.chunk_length - sizeof(SCTP_chunk_header);
1882         event_logi(VVERBOSE, "Got Cookie with %u bytes (incl. vlparam_header)! ", chunklen);
1883 
1884         signCookie((unsigned char *) cookie, chunklen, ourSignature);
1885 
1886         event_log(VVERBOSE, "Transmitted MD5 signature (in order to verify) : ");
1887         for (i = 0; i < 4; i++) {
1888             event_logiiii(VERBOSE, "%2.2x %2.2x %2.2x %2.2x",
1889                           cookieSignature[i * 4], cookieSignature[i * 4 + 1],
1890                           cookieSignature[i * 4 + 2], cookieSignature[i * 4 + 3]);
1891         }
1892 
1893         return (memcmp(cookieSignature, ourSignature, HMAC_LEN));
1894 
1895     } else {
1896         error_log(ERROR_MAJOR, "ch_goodCookie: chunk type not cookie");
1897         return FALSE;
1898     }
1899 }
1900 
1901 
1902 
1903 /****** create and read from heartbeat chunk ******************************************************/
1904 
1905 /**
1906  * ch_makeHeartbeat creates a heartbeatchunk.
1907  */
ch_makeHeartbeat(unsigned int sendingTime,unsigned int pathID)1908 ChunkID ch_makeHeartbeat(unsigned int sendingTime, unsigned int pathID)
1909 {
1910 
1911     SCTP_heartbeat *heartbeatChunk;
1912     unsigned char * key;
1913     int i;
1914     MD5_CTX ctx;
1915 
1916     /* creat Heartbeat chunk */
1917     heartbeatChunk = (SCTP_heartbeat *) malloc(sizeof(SCTP_simple_chunk));
1918     if (heartbeatChunk == NULL)
1919         error_log_sys(ERROR_FATAL, (short)errno);
1920 
1921     memset(heartbeatChunk, 0, sizeof(SCTP_simple_chunk));
1922 
1923     heartbeatChunk->chunk_header.chunk_id = CHUNK_HBREQ;
1924     heartbeatChunk->chunk_header.chunk_flags = 0;
1925     heartbeatChunk->chunk_header.chunk_length = sizeof(SCTP_heartbeat);
1926     heartbeatChunk->HB_Info.param_type = htons(VLPARAM_HB_INFO);
1927     heartbeatChunk->HB_Info.param_length = htons(sizeof(SCTP_heartbeat) - 4);
1928     heartbeatChunk->pathID = htonl((unsigned int) pathID);
1929     heartbeatChunk->sendingTime = htonl(sendingTime);
1930 
1931     key =  key_operation(KEY_READ);
1932     if (key == NULL) abort();
1933     memset(heartbeatChunk->hmac, 0, HMAC_LEN);
1934 
1935     MD5Init(&ctx);
1936     MD5Update(&ctx,(unsigned char*)(&heartbeatChunk->HB_Info) , sizeof(SCTP_heartbeat)-sizeof(SCTP_chunk_header));
1937     MD5Update(&ctx, key, SECRET_KEYSIZE);
1938     MD5Final(heartbeatChunk->hmac, &ctx);
1939 
1940     for (i = 0; i < 4; i++) {
1941         event_logiiii(VERBOSE, "%2.2x %2.2x %2.2x %2.2x",
1942                       heartbeatChunk->hmac[i * 4], heartbeatChunk->hmac[i * 4 + 1],
1943                       heartbeatChunk->hmac[i * 4 + 2], heartbeatChunk->hmac[i * 4 + 3]);
1944     }
1945 
1946     enterChunk((SCTP_simple_chunk *) heartbeatChunk, "created heartbeatChunk %u ");
1947 
1948     return freeChunkID;
1949 }
1950 
1951 /**
1952  * ch_verifyHeartbeat checks the signature of the received heartbeat.
1953  * @return TRUE, if HB signature was okay, else FALSE
1954  */
ch_verifyHeartbeat(ChunkID chunkID)1955 gboolean ch_verifyHeartbeat(ChunkID chunkID)
1956 {
1957     guchar hbSignature[HMAC_LEN];
1958     gboolean res = FALSE;
1959     int i;
1960 
1961     SCTP_heartbeat *heartbeatChunk;
1962     unsigned char * key;
1963 
1964     MD5_CTX ctx;
1965 
1966 
1967     if (chunks[chunkID] == NULL) {
1968         error_log(ERROR_MAJOR, "Invalid chunk ID");
1969         return FALSE;
1970     }
1971 
1972     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_HBACK) {
1973         heartbeatChunk =  (SCTP_heartbeat *)chunks[chunkID];
1974         key =  key_operation(KEY_READ);
1975         if (key == NULL) abort();
1976         /* store HMAC */
1977         memcpy(hbSignature, heartbeatChunk->hmac, HMAC_LEN);
1978 
1979         event_log(VERBOSE, "Got signature: ");
1980 
1981         for (i = 0; i < 4; i++) {
1982             event_logiiii(VERBOSE, "%2.2x %2.2x %2.2x %2.2x",
1983                       heartbeatChunk->hmac[i * 4], heartbeatChunk->hmac[i * 4 + 1],
1984                       heartbeatChunk->hmac[i * 4 + 2], heartbeatChunk->hmac[i * 4 + 3]);
1985         }
1986 
1987         memset(heartbeatChunk->hmac, 0, HMAC_LEN);
1988 
1989         MD5Init(&ctx);
1990         MD5Update(&ctx,(unsigned char*)(&heartbeatChunk->HB_Info), sizeof(SCTP_heartbeat)-sizeof(SCTP_chunk_header));
1991         MD5Update(&ctx, key, SECRET_KEYSIZE);
1992         MD5Final(heartbeatChunk->hmac, &ctx);
1993 
1994         event_log(VERBOSE, "Computed signature: ");
1995 
1996         for (i = 0; i < 4; i++) {
1997             event_logiiii(VERBOSE, "%2.2x %2.2x %2.2x %2.2x",
1998                       heartbeatChunk->hmac[i * 4], heartbeatChunk->hmac[i * 4 + 1],
1999                       heartbeatChunk->hmac[i * 4 + 2], heartbeatChunk->hmac[i * 4 + 3]);
2000         }
2001         if (memcmp(hbSignature, heartbeatChunk->hmac, HMAC_LEN) == 0) res = TRUE;
2002         else res = FALSE;
2003 
2004         return res;
2005 
2006     } else {
2007         error_log(ERROR_MINOR, "ch_verifyHeartbeat: chunk type not okay");
2008         return FALSE;
2009     }
2010 
2011 }
2012 
2013 /* ch_HBsendingTime reads the sending time of a heartbeat.
2014 */
ch_HBsendingTime(ChunkID chunkID)2015 unsigned int ch_HBsendingTime(ChunkID chunkID)
2016 {
2017     if (chunks[chunkID] == NULL) {
2018         error_log(ERROR_MAJOR, "Invalid chunk ID");
2019         return 0;
2020     }
2021 
2022     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_HBREQ ||
2023         chunks[chunkID]->chunk_header.chunk_id == CHUNK_HBACK) {
2024         return ntohl(((SCTP_heartbeat *) chunks[chunkID])->sendingTime);
2025     } else {
2026         error_log(ERROR_MINOR, "ch_HBsendingTime: chunk type not heartbeat or heartbeatAck");
2027         return 0;
2028     }
2029 }
2030 
2031 
2032 
2033 /* ch_HBpathID reads the path heartbeat on which the heartbeat was sent.
2034 */
ch_HBpathID(ChunkID chunkID)2035 unsigned int ch_HBpathID(ChunkID chunkID)
2036 {
2037     if (chunks[chunkID] == NULL) {
2038         error_log(ERROR_MAJOR, "Invalid chunk ID");
2039         return 0;
2040     }
2041 
2042     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_HBREQ ||
2043         chunks[chunkID]->chunk_header.chunk_id == CHUNK_HBACK) {
2044         return ntohl(((SCTP_heartbeat *) chunks[chunkID])->pathID);
2045     } else {
2046         error_log(ERROR_MINOR, "ch_HBsendingTime: chunk type not heartbeat or heartbeatAck");
2047         return 0;
2048     }
2049 }
2050 
2051 
2052 
2053 /***** create simple chunk **********************************************************************/
2054 
2055 /* ch_makeSimpleChunk creates a simple chunk. It can be used for parameterless chunks like
2056    abort, cookieAck and shutdownAck. It can also be used for chunks that have only variable
2057    length parameters like the error chunks
2058 */
ch_makeSimpleChunk(unsigned char chunkType,unsigned char flag)2059 ChunkID ch_makeSimpleChunk(unsigned char chunkType, unsigned char flag)
2060 {
2061     SCTP_simple_chunk *simpleChunk;
2062 
2063     /* creat simple chunk (used for abort, shutdownAck and cookieAck) */
2064     simpleChunk = (SCTP_simple_chunk *) malloc(sizeof(SCTP_simple_chunk));
2065     if (simpleChunk == NULL)
2066         error_log_sys(ERROR_FATAL, (short)errno);
2067 
2068     memset(simpleChunk, 0, sizeof(SCTP_simple_chunk));
2069 
2070     simpleChunk->chunk_header.chunk_id = chunkType;
2071     simpleChunk->chunk_header.chunk_flags = flag;
2072     simpleChunk->chunk_header.chunk_length = 0x0004;
2073 
2074     enterChunk(simpleChunk, "created simpleChunk %u ");
2075 
2076     return freeChunkID;
2077 }
2078 
2079 
2080 
2081 /***** write to and read from error chunk *******************************************************/
2082 /* ch_makeErrorChunk makes an error chunk */
2083 ChunkID
ch_makeErrorChunk(void)2084 ch_makeErrorChunk(void)
2085 {
2086     SCTP_error_chunk *errorChunk;
2087 
2088     /* creat init chunk */
2089     errorChunk = (SCTP_error_chunk *) malloc(sizeof(SCTP_error_chunk));
2090 
2091     if (errorChunk == NULL) error_log_sys(ERROR_FATAL, (short)errno);
2092 
2093     memset(errorChunk, 0, sizeof(SCTP_error_chunk));
2094 
2095     /* enter fixed part of init */
2096     errorChunk->chunk_header.chunk_id = CHUNK_ERROR;
2097     errorChunk->chunk_header.chunk_flags = 0x00;
2098     errorChunk->chunk_header.chunk_length = sizeof(SCTP_chunk_header);
2099 
2100     enterChunk((SCTP_simple_chunk *) errorChunk, "created errorChunk %u ");
2101 
2102     return freeChunkID;
2103 }
2104 
2105 void
ch_addUnrecognizedParameter(unsigned char * pos,ChunkID cid,unsigned short length,unsigned char * data)2106 ch_addUnrecognizedParameter(unsigned char* pos, ChunkID cid,
2107                             unsigned short length, unsigned char* data)
2108 
2109 {
2110     SCTP_error_cause * ec;
2111 
2112     if (pos == NULL) {
2113         error_log(ERROR_MAJOR, "Invalid chunk ID");
2114     }
2115     ec = (SCTP_error_cause*) pos;
2116     ec->cause_code = htons(VLPARAM_UNRECOGNIZED_PARAM);
2117     ec->cause_length = htons((unsigned short)(length+2*sizeof(unsigned short)));
2118     if (length > 0) {
2119         memcpy(&ec->cause_information, data, length);
2120     }
2121     writeCursor[cid] += (length + 2*sizeof(unsigned short));
2122     while ((writeCursor[cid] % 4) != 0) writeCursor[cid]++;
2123 }
2124 
2125 
2126 
2127 
2128 void
ch_addParameterToInitChunk(ChunkID initChunkID,unsigned short pCode,unsigned short dataLength,unsigned char * data)2129 ch_addParameterToInitChunk(ChunkID initChunkID, unsigned short pCode,
2130                            unsigned short dataLength, unsigned char* data)
2131 {
2132     SCTP_UnrecognizedParams *vlPtr = NULL;
2133     unsigned short index;
2134 
2135     if (chunks[initChunkID] == NULL) {
2136         error_log(ERROR_MAJOR, "Invalid chunk ID");
2137         return;
2138     }
2139     if (chunkCompleted[initChunkID]) {
2140         error_log(ERROR_MAJOR, " ch_addParameterToInit : chunk already completed");
2141         return;
2142     }
2143     index = writeCursor[initChunkID];
2144     vlPtr = (SCTP_UnrecognizedParams*) &(chunks[initChunkID]->simple_chunk_data[sizeof(SCTP_init_fixed)+index]);
2145 
2146     vlPtr->vlparam_header.param_type = htons(pCode);
2147     vlPtr->vlparam_header.param_length = htons((unsigned short)(dataLength+sizeof(SCTP_vlparam_header)));
2148     if (dataLength>0) memcpy(vlPtr->the_params, data, dataLength);
2149     writeCursor[initChunkID] += (dataLength + 2*sizeof(unsigned short));
2150     while ((writeCursor[initChunkID] % 4) != 0) writeCursor[initChunkID]++;
2151 
2152 }
2153 
2154 
2155 void
ch_enterErrorCauseData(ChunkID chunkID,unsigned short code,unsigned short length,unsigned char * data)2156 ch_enterErrorCauseData(ChunkID chunkID, unsigned short code,
2157                        unsigned short length, unsigned char* data)
2158 {
2159     SCTP_error_cause * ec;
2160     unsigned short index;
2161 
2162     if (chunks[chunkID] == NULL) {
2163         error_log(ERROR_MAJOR, "Invalid chunk ID");
2164         return;
2165     }
2166     if (chunkCompleted[chunkID]) {
2167         error_log(ERROR_MAJOR, " ch_enterErrorCauseData : chunk already completed");
2168         return;
2169     }
2170     if (chunks[chunkID]->chunk_header.chunk_id != CHUNK_ERROR && chunks[chunkID]->chunk_header.chunk_id != CHUNK_ABORT) {
2171         error_log(ERROR_MAJOR, " ch_enterErrorCauseData : Wrong chunk type");
2172         return;
2173     }
2174     index = writeCursor[chunkID];
2175     ec = (SCTP_error_cause*) &(chunks[chunkID]->simple_chunk_data[index]);
2176     ec->cause_code = htons(code);
2177     ec->cause_length = htons((unsigned short)(length+2*sizeof(unsigned short)));
2178     if (length > 0) {
2179         memcpy(&ec->cause_information, data, length);
2180     }
2181     writeCursor[chunkID] += (length + 2*sizeof(unsigned short));
2182     while ((writeCursor[chunkID] % 4) != 0) writeCursor[chunkID]++;
2183 
2184 }
2185 
2186 /* enters the staleness of a cookie into an error chunk. */
ch_enterStaleCookieError(ChunkID chunkID,unsigned int staleness)2187 void ch_enterStaleCookieError(ChunkID chunkID, unsigned int staleness)
2188 {
2189     SCTP_staleCookieError *staleCE;
2190 
2191     if (chunks[chunkID] == NULL) {
2192         error_log(ERROR_MAJOR, "Invalid chunk ID");
2193         return;
2194     }
2195 
2196     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_ERROR) {
2197         if (chunkCompleted[chunkID]) {
2198             error_log(ERROR_MAJOR, "ch_enterStaleCookieError: chunk already completed");
2199             return;
2200         }
2201 
2202 
2203         staleCE =
2204             (SCTP_staleCookieError *) & chunks[chunkID]->simple_chunk_data[writeCursor[chunkID]];
2205 
2206         staleCE->vlparam_header.param_type = htons(ECC_STALE_COOKIE_ERROR);
2207         staleCE->vlparam_header.param_length =
2208             htons((unsigned short) sizeof(SCTP_staleCookieError));
2209         staleCE->staleness = htonl(staleness);
2210 
2211         writeCursor[chunkID] += (unsigned short) sizeof(SCTP_staleCookieError);
2212 
2213         while ((writeCursor[chunkID] % 4) != 0) writeCursor[chunkID]++;
2214 
2215     } else {
2216         error_log(ERROR_MAJOR, "ch_enterStaleCookieError: chunk type not error");
2217     }
2218 
2219     return;
2220 }
2221 
2222 
2223 
2224 
2225 /* reads the staleness of a cookie from an error chunk. */
ch_stalenessOfCookieError(ChunkID chunkID)2226 unsigned int ch_stalenessOfCookieError(ChunkID chunkID)
2227 {
2228     short vl_param_curs;
2229     short vl_param_total_length;
2230     SCTP_staleCookieError *staleCE;
2231 
2232     if (chunks[chunkID] == NULL) {
2233         error_log(ERROR_MAJOR, "Invalid chunk ID");
2234         return 0;
2235     }
2236 
2237     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_ERROR) {
2238         vl_param_total_length =
2239             ((SCTP_simple_chunk *) chunks[chunkID])->chunk_header.chunk_length -
2240             sizeof(SCTP_chunk_header);
2241 
2242         vl_param_curs = retrieveVLParamFromString(ECC_STALE_COOKIE_ERROR, &((SCTP_simple_chunk *)
2243                                                                             chunks
2244                                                                             [chunkID])->
2245 
2246                                                   simple_chunk_data[0], vl_param_total_length);
2247 
2248         if (vl_param_curs >= 0) {
2249             /* found cookie staleness of cookie */
2250             staleCE = (SCTP_staleCookieError *) & chunks[chunkID]->simple_chunk_data[vl_param_curs];
2251             return ntohl(staleCE->staleness);
2252         } else {
2253             /* return 0, no effect on cookie lifetime */
2254             error_log(ERROR_MAJOR,
2255                       "ch_stalenessOfCookieError: error chunk does not contain a cookie stalenes");
2256             return 0;
2257         }
2258     } else {
2259         error_log(ERROR_MAJOR, "ch_stalenessOfCookieError: chunk type not error");
2260         return 0;
2261     }
2262 }
2263 
2264 
2265 /***** create and read from shutdown chunk ******************************************************/
2266 
2267 
2268 /* Creates a shutdown chunk.
2269 */
ch_makeShutdown(unsigned int _cummTSNacked)2270 ChunkID ch_makeShutdown(unsigned int _cummTSNacked)
2271 {
2272     SCTP_simple_chunk *shutdown_chunk;
2273     unsigned int *cummTSNacked;
2274 
2275     /* creat Shutdown chunk */
2276     shutdown_chunk = (SCTP_simple_chunk *) malloc(sizeof(SCTP_simple_chunk));
2277     if (shutdown_chunk == NULL)
2278         error_log_sys(ERROR_FATAL, (short)errno);
2279 
2280     memset(shutdown_chunk, 0, sizeof(SCTP_simple_chunk));
2281 
2282     shutdown_chunk->chunk_header.chunk_id = CHUNK_SHUTDOWN;
2283     shutdown_chunk->chunk_header.chunk_flags = 0x00;
2284     shutdown_chunk->chunk_header.chunk_length = 0x0008;
2285     cummTSNacked = (unsigned int *) (&(shutdown_chunk->simple_chunk_data[0]));
2286     *cummTSNacked = htonl(_cummTSNacked);
2287 
2288     enterChunk(shutdown_chunk, "created shutdown_chunk %u ");
2289 
2290     return freeChunkID;
2291 }
2292 
2293 
2294 
2295 
2296 /* reads the cummulative TSN acked from a shutdown chunk.
2297 */
ch_cummulativeTSNacked(ChunkID chunkID)2298 unsigned int ch_cummulativeTSNacked(ChunkID chunkID)
2299 {
2300     unsigned int *cummTSNacked;
2301 
2302     if (chunks[chunkID] == NULL) {
2303         error_log(ERROR_MAJOR, "Invalid chunk ID");
2304         return 0;
2305     }
2306 
2307     if (chunks[chunkID]->chunk_header.chunk_id == CHUNK_SHUTDOWN) {
2308         cummTSNacked =
2309             (unsigned int *) (&((SCTP_simple_chunk *) chunks[chunkID])->simple_chunk_data[0]);
2310         return ntohl(*cummTSNacked);
2311     } else {
2312         error_log(ERROR_MAJOR, "ch_cummulativeTSNacked: chunk type not init or initAck");
2313         return 0;
2314     }
2315 }
2316 
2317 
2318 
2319 /****** read from, make and delete generic chunk **************************************************/
2320 
2321 /* reads the chunks type of a chunk.
2322 */
ch_chunkType(ChunkID chunkID)2323 unsigned char ch_chunkType(ChunkID chunkID)
2324 {
2325     if (chunks[chunkID] == NULL) {
2326         error_log(ERROR_MAJOR, "Invalid chunk ID");
2327         return 0;
2328     }
2329 
2330     return chunks[chunkID]->chunk_header.chunk_id;
2331 }
2332 
2333 
2334 
2335 /* reads the chunks length of a chunks.
2336 */
ch_chunkLength(ChunkID chunkID)2337 unsigned short ch_chunkLength(ChunkID chunkID)
2338 {
2339     if (chunks[chunkID] == NULL) {
2340         error_log(ERROR_MAJOR, "Invalid chunk ID");
2341         return 0;
2342     }
2343 
2344     return chunks[chunkID]->chunk_header.chunk_length;
2345 }
2346 
2347 
2348 
2349 /* returns a pointer to the beginning of a simple chunk.
2350 */
ch_chunkString(ChunkID chunkID)2351 SCTP_simple_chunk *ch_chunkString(ChunkID chunkID)
2352 {
2353     if (chunks[chunkID] == NULL) {
2354         error_log(ERROR_MAJOR, "Invalid chunk ID");
2355         return NULL;
2356     }
2357 
2358     chunks[chunkID]->chunk_header.chunk_length =
2359         htons((unsigned short)(chunks[chunkID]->chunk_header.chunk_length + writeCursor[chunkID]));
2360     chunkCompleted[chunkID] = TRUE;
2361 
2362     return chunks[chunkID];
2363 }
2364 
2365 
2366 
2367 /*
2368  * swaps length INSIDE the packet !!!!!!!!!!! Phew ! and puts chunk pointer
2369  * into the current array of chunks -- does not need ch_deleteChunk !!
2370  */
ch_makeChunk(SCTP_simple_chunk * chunk)2371 ChunkID ch_makeChunk(SCTP_simple_chunk * chunk)
2372 {
2373 
2374     /*
2375      * swaps length INSIDE the packet !!!!!!!!!!! Phew ! and enters chunk
2376      * into the current list
2377      */
2378     chunk->chunk_header.chunk_length = ntohs(chunk->chunk_header.chunk_length);
2379 
2380     enterChunk(chunk, "created chunk from string %u ");
2381 
2382     return freeChunkID;
2383 }
2384 
2385 
2386 /* ch_deleteChunk removes the chunk from the array of chunks and frees the
2387    memory allocated for that chunk.
2388 */
ch_deleteChunk(ChunkID chunkID)2389 void ch_deleteChunk(ChunkID chunkID)
2390 {
2391     unsigned int cid;
2392 
2393     cid = chunkID;
2394 
2395     if (chunks[chunkID] != NULL) {
2396         event_logi(INTERNAL_EVENT_0, "freed chunk %u", cid);
2397         free(chunks[chunkID]);
2398         chunks[chunkID] = NULL;
2399     } else {
2400         error_log(ERROR_MAJOR, "chunk already freed");
2401     }
2402 }
2403 
2404 
2405 
2406 /* ch_forgetChunk removes the chunk from the array of chunks without freeing the
2407    memory allocated for that chunk.
2408    This is used in the following cases:
2409    - the caller wants to keep the chunk for retransmissions.
2410    - the chunk was created with ch_makeChunk and the pointer to the chunk points
2411      into an SCTP-message, which was allocated as a whole. In this case the chunk
2412      can not be freed here.
2413 */
ch_forgetChunk(ChunkID chunkID)2414 void ch_forgetChunk(ChunkID chunkID)
2415 {
2416     unsigned int cid;
2417 
2418     cid = chunkID;
2419 
2420     if (chunks[chunkID] != NULL) {
2421         chunks[chunkID] = NULL;
2422         event_logi(INTERNAL_EVENT_0, "forgot chunk %u", cid);
2423     } else {
2424         error_log(ERROR_MAJOR, "chunk already forgotten");
2425     }
2426 }
2427