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