comparison src/g23m-fad/ip/ip_kerf.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e78acac3d88 1:fa8dc04885d8
1 /*
2 +----------------------------------------------------------------------------
3 | Project :
4 | Modul :
5 +----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +----------------------------------------------------------------------------
17 | Purpose : This Modul defines the functions for processing
18 | of incomming primitives for the component
19 | Internet Protocol of the mobile station
20 +----------------------------------------------------------------------------
21 */
22
23 #define ENTITY_IP
24
25 /*==== INCLUDES ===================================================*/
26
27 #include <string.h>
28 #include "typedefs.h"
29 #include "pconst.cdg"
30 #include "vsi.h"
31 #include "macdef.h" /* Get PFREE_DESC2 */
32 #include "pconst.cdg"
33 #include "custom.h"
34 #include "gsm.h"
35 #include "cnf_ip.h"
36 #include "mon_ip.h"
37 #include "prim.h"
38 #include "pei.h"
39 #include "tok.h"
40 #include "ccdapi.h"
41 #include "dti.h"
42 #include "ip.h"
43 #include "ip_udp.h"
44
45 /*
46 +--------------------------------------------------------------------+
47 | PROJECT : WAP MODULE : ip_kerf.c |
48 | STATE : code ROUTINE : ip_packet_validator |
49 +--------------------------------------------------------------------+
50
51 PURPOSE : Checks for IP packet validity
52 */
53 BOOL ip_packet_validator (T_desc_list2 * desc_list)
54 {
55 TRACE_FUNCTION ("ip_packet_validator()");
56
57 if (desc_list == NULL)
58 {
59 TRACE_ERROR ("desc_list == NULL in IP validator.");
60 return FALSE;
61 }
62
63 {
64 /* Loop once through all the list */
65 register T_desc2 * desc = (T_desc2 *) desc_list->first;
66 register unsigned length = 0;
67 while (desc != NULL)
68 {
69 /* Check consistency of descs */
70 if (desc->size < desc->offset + desc->len)
71 {
72 TRACE_ERROR (
73 "Packet dropped: "
74 "desc->size < desc->offset + desc->len in IP validator."
75 );
76 return FALSE;
77 /* This is a mistake. Must be DTI1. */
78 /* desc->offset = 0; */
79 /* desc->size = desc->len; */
80 }
81 /* Make sure that all offsets are 0 */
82 if (desc->offset != 0)
83 {
84 memmove (desc->buffer, desc->buffer + desc->offset, desc->len);
85 desc->offset = 0;
86 }
87 /* Calculate the sum of lengths */
88 length += desc->len;
89 desc = (T_desc2 *) desc->next;
90 }
91 /* Check desc_list->list_len */
92 if (desc_list->list_len != length)
93 {
94 TRACE_ERROR (
95 "Packet dropped: "
96 "desc_list->list_len != length in IP validator."
97 );
98 return FALSE;
99 /* This is a mistake. But we could live with it. */
100 /* desc_list->list_len = (USHORT) length; */
101 }
102
103 /* Need at least LEN_IP_HEADER_B bytes for one header */
104 if (length < LEN_IP_HEADER_B)
105 {
106 TRACE_ERROR (
107 "Packet dropped: "
108 "length < LEN_IP_HEADER_B in IP validator."
109 );
110 return FALSE;
111 }
112
113 /* Have enough bytes, but they may be distributed */
114 desc = (T_desc2 *) desc_list->first;
115 if (desc->len < LEN_IP_HEADER_B)
116 {
117 /* Collect all bytes in one desc */
118 T_desc2 * bigdesc = M_ALLOC (offsetof (T_desc2, buffer) + length);
119 if (bigdesc == NULL)
120 {
121 TRACE_ERROR ("Not enough memory in IP validator.");
122 return FALSE;
123 }
124
125 bigdesc->next = 0;
126 bigdesc->offset = 0;
127 bigdesc->len = (USHORT) length;
128 bigdesc->size = (USHORT) length;
129
130 /* Loop again through all the list */
131 length = 0;
132 while (desc != NULL)
133 {
134 T_desc2 * removable = desc;
135 memcpy (bigdesc->buffer + length, desc->buffer, desc->len);
136 length += desc->len;
137 desc = (T_desc2 *) desc->next;
138 MFREE (removable);
139 }
140 desc_list->first = (ULONG) bigdesc;
141 desc = bigdesc;
142 }
143
144 /* Need at least GET_IP_HEADER_LEN_B() bytes for the IP header */
145 if (length < (unsigned) GET_IP_HEADER_LEN_B (desc->buffer))
146 {
147 TRACE_ERROR (
148 "Packet dropped: "
149 "length < GET_IP_HEADER_LEN_B() in IP validator."
150 );
151 return FALSE;
152 }
153
154 /* Survived */
155 return TRUE;
156 }
157 }
158
159 /*
160 +--------------------------------------------------------------------+
161 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
162 | STATE : code ROUTINE : free_primitive_data_ind |
163 +--------------------------------------------------------------------+
164 *
165 * Set a DTI_DATA_IND primitive free and the pointer to NULL
166 */
167 void free_primitive_data_ind (T_DTI2_DATA_IND ** dti_data_ind)
168 {
169 TRACE_FUNCTION ("free_primitive_data_ind()");
170
171 if (dti_data_ind != NULL && *dti_data_ind != NULL) {
172 PFREE_DESC2 (* dti_data_ind);
173 *dti_data_ind = NULL;
174 }
175 }
176
177 /*
178 +--------------------------------------------------------------------+
179 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
180 | STATE : code ROUTINE : free_primitive_data_req |
181 +--------------------------------------------------------------------+
182 *
183 * Set a DTI_DATA_REQ primitive free and the pointer to NULL
184 */
185 void free_primitive_data_req (T_DTI2_DATA_REQ ** dti_data_req)
186 {
187 TRACE_FUNCTION ("free_primitive_data_req()");
188
189 if (dti_data_req != NULL && *dti_data_req != NULL) {
190 PFREE_DESC2 (* dti_data_req);
191 *dti_data_req = NULL;
192 }
193 }
194
195 /*
196 +--------------------------------------------------------------------+
197 | PROJECT : WAP MODULE : IP |
198 | STATE : code ROUTINE : set_desc_len |
199 +--------------------------------------------------------------------+
200 *
201 * Set the new desc length and fix desc_list length
202 */
203 void set_desc_len (T_desc_list2 * desc_list, T_desc2 * desc, USHORT len_desc)
204 {
205 TRACE_FUNCTION ("set_desc_len()");
206
207 desc_list->list_len = (USHORT) (desc_list->list_len + len_desc - desc->len);
208 desc->len = len_desc;
209 }
210
211 /*
212 +--------------------------------------------------------------------+
213 | PROJECT : WAP MODULE : IP |
214 | STATE : code ROUTINE : del_rest_descs |
215 +--------------------------------------------------------------------+
216 *
217 * Free the next desc(s) from desc. Fix the list_len in desc_list
218 */
219 void del_rest_descs (T_desc_list2 * desc_list, T_desc2 * desc)
220 {
221 BOOL go = TRUE;
222 T_desc2 * p_desc_last, * p_desc_start;
223
224 TRACE_FUNCTION ("del_rest_descs()");
225
226 if (desc->next > 0)
227 {
228 p_desc_start = desc;
229 desc = (T_desc2 *) desc->next;
230
231 do
232 {
233 p_desc_last = desc;
234
235 if (desc->next > 0)
236 desc = (T_desc2 *) desc->next;
237 else
238 go = FALSE;
239
240 desc_list->list_len = (USHORT)
241 (desc_list->list_len - p_desc_last->len);
242 MFREE (p_desc_last);
243 }
244 while (go);
245
246 desc = p_desc_start;
247 desc->next = 0;
248 }
249 }
250
251 /*
252 +--------------------------------------------------------------------+
253 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
254 | STATE : code ROUTINE : del_descs |
255 +--------------------------------------------------------------------+
256 *
257 * Free the desc(s)
258 */
259 void del_descs (T_desc2 * desc)
260 {
261 BOOL go = TRUE;
262 T_desc2 * p_desc_last;
263
264 TRACE_FUNCTION ("del_descs()");
265
266 do
267 {
268 p_desc_last = desc;
269
270 if (desc->next > 0)
271 desc = (T_desc2 *) desc->next;
272 else
273 go = FALSE;
274
275 MFREE (p_desc_last);
276 }
277 while (go);
278 }
279
280 /** filter_out_in_desc
281 *
282 * cuts length bytes out of a T_desc2::buffer, starting at 'start'.
283 *
284 * @param desc Pointer to a T_desc2
285 * @param start Start of the block to be cut out
286 * @param length Length of the block to be cut out
287 *
288 * @return TRUE if parameters are valid, FALSE if parameters are invalid
289 */
290 static BOOL filter_out_in_desc (
291 T_desc2 * desc,
292 USHORT start,
293 USHORT length
294 ) {
295 TRACE_FUNCTION ("filter_out_in_desc()");
296
297 if (desc != NULL && start + length <= desc->len) {
298 memmove (
299 desc->buffer + start,
300 desc->buffer + start + length,
301 desc->len - start - length
302 );
303 desc->len = (USHORT) (desc->len - length);
304 return TRUE;
305 } else {
306 TRACE_ERROR ("Parameters are invalid in filter_out_in_desc().");
307 return FALSE;
308 }
309 }
310
311 /** truncate_descs
312 *
313 * truncates a T_desc_list2 to no more than new_length bytes.
314 *
315 * @param desc_list Pointer to a T_desc_list2
316 * @param new_length Maximal new length of that T_desc_list2
317 */
318 void truncate_descs (T_desc_list2 * desc_list, USHORT new_length)
319 {
320 TRACE_FUNCTION ("truncate_descs()");
321
322 if (desc_list != NULL)
323 {
324 T_desc2 ** pp_desc = (T_desc2 **) & desc_list->first;
325 desc_list->list_len = 0; /* Will be recalculated, anyway */
326
327 /* First a loop over all T_descs which will remain. */
328 while (*pp_desc != NULL && new_length != 0)
329 {
330 if (new_length < (*pp_desc)->len)
331 (*pp_desc)->len = new_length;
332 new_length = (USHORT) (new_length - (*pp_desc)->len);
333 desc_list->list_len = /* Recalculation */
334 (USHORT) (desc_list->list_len + (*pp_desc)->len);
335 pp_desc = (T_desc2 **) & (*pp_desc)->next;
336 }
337
338 /* Second a loop over all T_descs which have to be deleted, if any. */
339 while (*pp_desc != NULL)
340 {
341 T_desc2 * p_desc_removable = *pp_desc;
342 *pp_desc = (T_desc2 *) p_desc_removable->next;
343 MFREE (p_desc_removable);
344 }
345
346 /* This way, new_length==0 at function call results in
347 * desc_list->first==NULL at function return. */
348
349 /* Third a loop over all T_descs which have to be created, if any.
350 * (If it were Prokrustes, not truncation,
351 * we would have to allocate new T_descs here.)
352 * while (new_length != 0) { ... } */
353 }
354 else
355 {
356 TRACE_ERROR ("truncate_descs() called without T_desc_list2.");
357 TRACE_ASSERT (0);
358 }
359 }
360
361 /*
362 +--------------------------------------------------------------------+
363 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
364 | STATE : code ROUTINE : insert_sort_descs |
365 +--------------------------------------------------------------------+
366 *
367 * Insert a new descriptor sorted by fragment offset.
368 * The less value at first. Filter out descs with same offset.
369 */
370 static void insert_sort_desc (T_desc_list2 * desc_list, T_desc2 * p_new_desc)
371 {
372 if (desc_list != NULL && p_new_desc != NULL)
373 {
374 T_desc2 * desc;
375 T_desc2 * p_desc_last;
376 UBYTE * ip_header;
377 USHORT offset, new_offset;
378
379 offset = 0xffff;
380 ip_header = p_new_desc->buffer;
381 new_offset = (USHORT) GET_IP_FRAG_OFFSET (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
382 desc = (T_desc2 *) desc_list->first;
383 p_desc_last = NULL;
384
385 while (desc NEQ NULL)
386 {
387 ip_header = desc->buffer;
388 offset = (USHORT) GET_IP_FRAG_OFFSET (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
389 if (new_offset <= offset)
390 break;
391 p_desc_last = desc;
392 desc = (T_desc2 *) desc->next;
393 }
394
395 if (new_offset EQ offset)
396 {
397 /* Two descriptors with the same offset
398 * Throw away the new one */
399 MFREE (p_new_desc);
400 }
401 else
402 {
403 /* Insert descriptor after p_desc_last */
404 if (p_desc_last EQ NULL)
405 {
406 p_new_desc->next = desc_list->first;
407 desc_list->first = (ULONG) p_new_desc;
408 }
409 else
410 {
411 p_new_desc->next = p_desc_last->next;
412 p_desc_last->next = (ULONG) p_new_desc;
413 }
414
415 /* Add the length of the new descriptor */
416 desc_list->list_len = (USHORT) (desc_list->list_len + p_new_desc->len);
417 }
418 }
419 }
420
421 /*
422 +--------------------------------------------------------------------+
423 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
424 | STATE : code ROUTINE : reassemble_fragments |
425 +--------------------------------------------------------------------+
426 *
427 * Reassemble fragments coming in downlink
428 */
429 void reassemble_fragments (
430 T_DTI2_DATA_IND ** dti_data_ind,
431 T_LOLA * p_dl,
432 UBYTE * ip_header,
433 BOOL first_segment,
434 /* BOOL middle_segment, */
435 BOOL last_segment /*,*/
436 /* USHORT fragm_offset */
437 ) {
438 USHORT fragm_id, header_len_b, offset;
439 UBYTE fragm_prot;
440 ULONG server_source_addr;
441 BOOL found_source_addr = FALSE;
442
443 TRACE_FUNCTION ("reassemble_fragments()");
444
445 fragm_id = (USHORT) GET_IP_IDENT (ip_header);
446 fragm_prot = GET_IP_PROT (ip_header);
447 server_source_addr = GET_IP_SOURCE_ADDR (ip_header);
448
449 /* Check source address from server */
450 p_dl->pos_server = 0;
451 do
452 {
453 if (p_dl->ip_source_addr_segment[p_dl->pos_server] NEQ server_source_addr)
454 p_dl->pos_server++;
455 else
456 found_source_addr = TRUE;
457
458 } while (! found_source_addr && p_dl->pos_server < MAX_SEGM_SERVER);
459
460 /* Select the server - by only one server p_dl->pos_server = 0 */
461 if (p_dl->pos_server EQ MAX_SEGM_SERVER)
462 p_dl->pos_server = 0;
463
464 p_dl->ip_source_addr_segment[p_dl->pos_server] = server_source_addr;
465
466 /* Check if it is the first or the last segment */
467 if (first_segment)
468 p_dl->got_first_segment[p_dl->pos_server] = TRUE;
469
470 if (last_segment)
471 p_dl->got_last_segment[p_dl->pos_server] = TRUE;
472
473 /* Is it the first of any segment type? */
474 if (p_dl->state_reassembly[p_dl->pos_server] EQ NO_SEGMENTS)
475 {
476 p_dl->data_ind_reassembly[p_dl->pos_server] = *dti_data_ind;
477 p_dl->state_reassembly[p_dl->pos_server] = READ_SEGMENT;
478 p_dl->id_reassemble[p_dl->pos_server] = fragm_id;
479 p_dl->prot_reassemble[p_dl->pos_server] = fragm_prot;
480
481 /* Start reassembly timer */
482
483 /* Implementation problem: the timer index must be
484 * layer * MAX_SEGM_SERVER + p_dl->pos_server. The
485 * layer variable is not forwarded to the function.
486 * It works, because layer is ever set to 0 in the moment. */
487
488 vsi_t_start (VSI_CALLER p_dl->pos_server, TIME_REASSEMBLY);
489 p_dl->timer_reass_running[p_dl->pos_server] = TRUE;
490 }
491 /* Check the fragment ID and protocol. If not the same - free resources */
492 else if (
493 (p_dl->id_reassemble[p_dl->pos_server] NEQ fragm_id) OR
494 (p_dl->prot_reassemble[p_dl->pos_server] NEQ fragm_prot)
495 ) {
496 if (p_dl->timer_reass_running[p_dl->pos_server])
497 {
498 /* Implementation problem: the timer index must be
499 * layer * MAX_SEGM_SERVER + p_dl->pos_server. The
500 * layer variable is not forwarded to the function.
501 * It works, because layer is ever set to 0 in the moment. */
502
503 csf_stop_timer (p_dl->pos_server);
504 p_dl->timer_reass_running[p_dl->pos_server] = FALSE;
505 }
506
507 p_dl->drop_packet = TRUE;
508 p_dl->state_reassembly[p_dl->pos_server] = NO_SEGMENTS;
509
510 free_primitive_data_ind (p_dl->data_ind_reassembly + p_dl->pos_server);
511
512 /* Note: We could generate an ICMP packet */
513 return;
514 }
515 else /* Got correct segments before */
516 {
517 /* Note: The whole datagram must be in the same descriptor */
518 /* Note: The timeout value should be changed to MAX (TTL, TIME_REASSEMBLY) */
519
520 BOOL all_fragments_received = FALSE;
521
522 T_desc_list2 * desc_list = & p_dl->data_ind_reassembly[p_dl->pos_server]->desc_list2;
523 T_desc2 * desc = (T_desc2 *) p_dl->dti_data_ind->desc_list2.first;
524
525 if (desc == NULL || (T_desc2 *) desc_list->first == NULL)
526 {
527 TRACE_ERROR ("Pointer is NULL.");
528 return;
529 }
530
531 /* Insert the descriptor in the right position, according to the offset */
532 insert_sort_desc (desc_list, desc);
533
534 /* Check if got all fragments */
535
536 if (
537 p_dl->got_first_segment[p_dl->pos_server] AND
538 p_dl->got_last_segment[p_dl->pos_server]
539 ) {
540 BOOL go = TRUE;
541 USHORT data_len, next_offset;
542 UBYTE * ip_packet;
543 desc = (T_desc2 *) desc_list->first;
544 ip_packet = desc->buffer;
545 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_packet);
546 data_len = (USHORT) (desc->len - header_len_b);
547 next_offset = 0;
548 do
549 {
550 if ((T_desc2 *) desc->next != NULL)
551 {
552 desc = (T_desc2 *) desc->next;
553 ip_packet = desc->buffer;
554 next_offset = (USHORT) GET_IP_FRAG_OFFSET_B (ip_packet);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
555 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_packet);
556
557 if ((T_desc2 *) desc->next != NULL)
558 data_len = (USHORT) (data_len + desc->len - header_len_b);
559 }
560 else
561 go = FALSE;
562 }
563 while (go);
564
565 if (data_len >= next_offset)
566 all_fragments_received = TRUE;
567 }
568
569 /* Reassemble the fragments */
570
571 if (all_fragments_received)
572 {
573 BOOL go = TRUE;
574 USHORT len_fragments, header_len_b_first;
575 T_desc2 * p_desc_first, * p_desc_last;
576 UBYTE * ip_packet;
577
578 p_dl->state_reassembly[p_dl->pos_server] = NO_SEGMENTS;
579
580 if (
581 desc_list == NULL ||
582 (T_desc2 *) desc_list->first == NULL ||
583 (T_desc2 *) ((T_desc2*)desc_list->first)->next == NULL
584 ) {
585 TRACE_ERROR ("Pointer is NULL.");
586 return;
587 }
588
589 /* Fix the first desc */
590 p_desc_first = (T_desc2 *) desc_list->first;
591 ip_packet = p_desc_first->buffer;
592 header_len_b_first = (USHORT) GET_IP_HEADER_LEN_B (ip_packet);
593
594 /* Start from next desc */
595 desc = (T_desc2 *) p_desc_first->next;
596 ip_packet = desc->buffer;
597 offset = (USHORT) GET_IP_FRAG_OFFSET_B (ip_packet);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
598 p_desc_first->len = (USHORT) (offset + header_len_b_first);
599 len_fragments = offset;
600
601 do
602 {
603 if (desc->next NEQ 0)
604 {
605 p_desc_last = desc;
606 desc = (T_desc2 *) desc->next;
607
608 /* Get the fragment offset */
609 ip_packet = desc->buffer;
610 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_packet);
611 offset = (USHORT) GET_IP_FRAG_OFFSET_B (ip_packet);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
612
613 /* Filter out IP header */
614 ip_packet = p_desc_last->buffer;
615 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_packet);
616 filter_out_in_desc (p_desc_last, 0, header_len_b);
617
618 len_fragments = (USHORT) (len_fragments + p_desc_last->len);
619 }
620 else
621 {
622 go = FALSE;
623
624 /* Filter out last IP header */
625 ip_packet = desc->buffer;
626 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_packet);
627 filter_out_in_desc (desc, 0, header_len_b);
628
629 len_fragments = (USHORT) (len_fragments + desc->len);
630 }
631 }
632 while (go);
633
634 /* Build the IP datagram */
635
636 /* Implementation problem: the timer index must be
637 * layer * MAX_SEGM_SERVER + p_dl->pos_server. The
638 * layer variable is not forwarded to the function.
639 * It works, because layer is ever set to 0 in the moment. */
640
641 csf_stop_timer (p_dl->pos_server);
642 p_dl->timer_reass_running[p_dl->pos_server] = FALSE;
643 /* PFREE (dti_data_ind); */
644 /* Is being freed elsewhere. Would anyway have false level of indirection. */
645 p_dl->data_ind_reassembly[p_dl->pos_server]->desc_list2.list_len =
646 (USHORT) (len_fragments + header_len_b_first);
647
648 *dti_data_ind = p_dl->data_ind_reassembly[p_dl->pos_server];
649 p_desc_first = (T_desc2 *) (*dti_data_ind)->desc_list2.first;
650 ip_packet = p_desc_first->buffer;
651
652 {
653 ULONG dest_addr;
654 UBYTE ttl;
655 dest_addr = GET_IP_DEST_ADDR (ip_packet);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
656 ttl = GET_IP_TTL (ip_packet);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
657
658 build_ip_header (
659 ip_packet,
660 fragm_id,
661 (UBYTE) (header_len_b_first >> 2),
662 NORMAL_SERVICE,
663 ttl,
664 p_dl->ip_source_addr_segment[p_dl->pos_server],
665 dest_addr,
666 (UBYTE) (len_fragments + header_len_b_first),
667 NO_OFFSET_FRAG,
668 FLAG_NOT_SET,
669 FLAG_NOT_SET,
670 fragm_prot
671 );
672 }
673 p_dl->data_ind_reassembly[p_dl->pos_server] = NULL;
674 }
675 /* else */
676 /* PFREE (dti_data_ind); */
677 /* Is being freed elsewhere. Would anyway have false level of indirection. */
678 }
679
680 }
681
682 /*
683 +--------------------------------------------------------------------+
684 | PROJECT : WAP MODULE : IP |
685 | STATE : code ROUTINE : put_desc_first_pos |
686 +--------------------------------------------------------------------+
687 *
688 * Put desc on the first position of a desc_list.
689 * Set the new list_len in desc_list.
690 */
691 void put_desc_first_pos (T_desc_list2 * desc_list, T_desc2 * p_desc_new)
692 {
693 ULONG help;
694 T_desc2 * p_desc_help;
695
696 TRACE_FUNCTION ("put_desc_first_pos()");
697
698 p_desc_help = (T_desc2 *) desc_list->first;
699
700 if (p_desc_help NEQ p_desc_new)
701 {
702 help = desc_list->first;
703 desc_list->first = (ULONG) p_desc_new;
704 p_desc_new->next = help;
705 desc_list->list_len = (USHORT) (desc_list->list_len + p_desc_new->len);
706 }
707 }
708
709 /*
710 +--------------------------------------------------------------------+
711 | PROJECT : GSM-FaD (8444) MODULE : IP_KER |
712 | STATE : code ROUTINE : copy_from_descs_to_desc |
713 +--------------------------------------------------------------------+
714 *
715 * Copy data from one or more descs into desc_new. Possible to use offset.
716 */
717 void copy_from_descs_to_desc (
718 T_desc2 ** desc,
719 T_desc2 * desc_new,
720 USHORT copy_len,
721 USHORT offset_desc,
722 USHORT offset_desc_new,
723 USHORT * pos_copy,
724 USHORT * total_len_copy
725 ) {
726 BOOL go = TRUE;
727 *pos_copy = offset_desc;
728 *total_len_copy = 0;
729
730 do
731 {
732 while (
733 (*pos_copy < (*desc)->len) AND
734 (offset_desc_new < desc_new->len) AND
735 (*total_len_copy < copy_len)
736 ) {
737 desc_new->buffer[offset_desc_new] = (*desc)->buffer[*pos_copy];
738 offset_desc_new ++;
739 (*pos_copy)++;
740 (*total_len_copy)++;
741 }
742
743 if (
744 (*total_len_copy >= copy_len) OR
745 (offset_desc_new >= desc_new->len)
746 ) {
747 go = FALSE;
748 }
749 else
750 {
751 if (*pos_copy >= (*desc)->len)
752 {
753 if ((*desc)->next > 0)
754 {
755 *desc = (T_desc2 *) (*desc)->next;
756 *pos_copy = 0;
757 }
758 else
759 {
760 go = FALSE;
761 }
762 }
763 }
764 }
765 while (go);
766 }
767
768 /*
769 +--------------------------------------------------------------------+
770 | PROJECT : WAP MODULE : IP |
771 | STATE : code ROUTINE : make_new_desc |
772 +--------------------------------------------------------------------+
773 *
774 * Malloc a new desc. Init buffer 0 if buff_init_0 = TRUE
775 */
776 BOOL make_new_desc (
777 T_desc2 ** p_desc_new,
778 USHORT malloc_len,
779 BOOL buff_init_0
780 ) {
781 TRACE_FUNCTION ("make_new_desc()");
782
783 MALLOC (*p_desc_new, offsetof (T_desc2, buffer) + malloc_len);
784 /* The target compiler issues a warning
785 * "pointer type conversion may violate alignment constraints"
786 * here and everywhere where MALLOC is being used. */
787
788 if (*p_desc_new EQ 0)
789 return FALSE;
790
791 if (buff_init_0)
792 {
793 USHORT i;
794 for (i = 0; i < malloc_len; i++)
795 (*p_desc_new)->buffer[i] = 0;
796 }
797 (*p_desc_new)->next = 0;
798 (*p_desc_new)->offset = 0;
799 (*p_desc_new)->len = malloc_len;
800 (*p_desc_new)->size = malloc_len;
801 return TRUE;
802 }
803
804 #if 0
805 /*
806 +--------------------------------------------------------------------+
807 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
808 | STATE : code ROUTINE : sort_descs_id_up |
809 +--------------------------------------------------------------------+
810 *
811 * Sort the descs with fragment offset. The less value at
812 * first. Filter out descs with same offset.
813 */
814 USHORT sort_descs_id_up (
815 T_desc_list * desc_list,
816 ULONG sort_array[2][MAX_SEGMENTS]
817 ) {
818 T_desc * desc;
819 USHORT i, n_descs, code;
820 BOOL go = TRUE;
821 ULONG addr, wert;
822 UBYTE * ip_header;
823
824 TRACE_FUNCTION ("sort_descs_id_up()");
825
826 desc = (T_desc *) desc_list->first;
827 n_descs = 0;
828 code = GO_ON_SEGMENTING;
829
830 if (desc->next > 0)
831 {
832 /* Write desc address and search-value into sort_array */
833
834 desc = (T_desc *) desc_list->first;
835
836 i = 0;
837 ip_header = desc->buffer;
838 sort_array[1][i] = GET_IP_FRAG_OFFSET (ip_header);
839 sort_array[0][i++] = desc_list->first;
840
841 do
842 {
843 if (desc->next > 0 AND i < MAX_SEGMENTS)
844 {
845 desc = (T_desc *) desc->next;
846 sort_array[0][i] = (ULONG) desc;
847 ip_header = desc->buffer;
848 sort_array[1][i++] = GET_IP_FRAG_OFFSET (ip_header);
849 }
850 else
851 go = FALSE;
852 }
853 while (go);
854
855 /* Sort the array if not overflow */
856
857 if (i < MAX_SEGMENTS)
858 {
859 n_descs = i;
860
861 for (i = 0; i < n_descs - 1; i++)
862 {
863 USHORT min, j;
864 min = i;
865
866 for (j = i + 1; j < n_descs; j++)
867 if (sort_array[1][j] < sort_array[1][min])
868 min = j;
869
870 addr = sort_array[0][i];
871 wert = sort_array[1][i];
872 sort_array[0][i] = sort_array[0][min];
873 sort_array[1][i] = sort_array[1][min];
874 sort_array[0][min] = addr;
875 sort_array[1][min] = wert;
876 }
877
878 /* Filter out descs with same fragment offset */
879 {
880 ULONG v1;
881 USHORT j, k, len;
882 len = n_descs - 1;
883 i = 0;
884 while (i < len)
885 {
886 v1 = sort_array[1][i];
887 j = i + 1;
888 if (v1 EQ sort_array[1][j])
889 {
890 k = j;
891 n_descs--;
892 while (k <= len)
893 {
894 sort_array[0][k] = sort_array[0][k + 1];
895 sort_array[1][k] = sort_array[1][k + 1];
896 k++;
897 }
898 len--;
899 }
900 if (sort_array[1][i] NEQ sort_array[1][i + 1])
901 i++;
902 }
903 }
904
905 /* Put the descs together and correct the desc_list->list_len */
906
907 desc_list->first = sort_array[0][0];
908 desc = (T_desc *) sort_array[0][0];
909 desc_list->list_len = 0;
910 desc_list->list_len = desc->len;
911
912 for (i = 1; i < n_descs; i++)
913 {
914 desc->next = sort_array[0][i];
915 desc = (T_desc *) desc->next;
916 desc_list->list_len = desc_list->list_len + desc->len;
917 }
918
919 desc->next = 0;
920 }
921 else
922 code = NO_SPACE_SEGMENTING;
923
924 desc = (T_desc *) desc_list->first;
925 }
926 return code;
927 }
928 #endif
929
930 /*
931 +--------------------------------------------------------------------+
932 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
933 | STATE : code ROUTINE : build_ip_header |
934 +--------------------------------------------------------------------+
935 *
936 * Build IP header
937 */
938 void build_ip_header (
939 UBYTE * ip_header_new,
940 USHORT identity,
941 UBYTE header_len,
942 UBYTE type_of_service,
943 UBYTE ttl,
944 ULONG src_addr,
945 ULONG dest_addr,
946 USHORT total_len,
947 USHORT fragm_offset,
948 UBYTE df_flag,
949 UBYTE mf_flag,
950 UBYTE prot
951 ) {
952 USHORT chk_sum;
953
954 TRACE_FUNCTION ("build_ip_header()");
955
956 SET_IP_VERSION (ip_header_new, IP_VERSION);
957 /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer) */
958 {
959 SET_IP_HEADER_LEN (ip_header_new, header_len);
960 SET_IP_TYPE_OF_SERVICE (ip_header_new, type_of_service);
961 SET_IP_TOTAL_LEN (ip_header_new, total_len);
962 SET_IP_IDENT (ip_header_new, identity);
963 SET_IP_OFF_FLAG (ip_header_new, FLAG_NOT_SET);
964 SET_IP_DF_FLAG (ip_header_new, df_flag);
965 SET_IP_MF_FLAG (ip_header_new, mf_flag);
966 SET_IP_FRAG_OFFSET (ip_header_new, fragm_offset);
967 SET_IP_PROT (ip_header_new, prot);
968 SET_IP_TTL (ip_header_new, ttl);
969 SET_IP_SOURCE_ADDR (ip_header_new, src_addr);
970 SET_IP_DEST_ADDR (ip_header_new, dest_addr);
971 RESET_IP_CHECKSUM (ip_header_new);
972 chk_sum = inet_checksum (ip_header_new, (USHORT) (header_len * 4));
973 SET_IP_CHECKSUM (ip_header_new, chk_sum);
974 }
975 }
976
977 /*
978 +--------------------------------------------------------------------+
979 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
980 | STATE : code ROUTINE : build_icmp_packet |
981 +--------------------------------------------------------------------+
982 *
983 * Build IP icmp packet without payload
984 */
985 void build_icmp_packet (
986 USHORT header_len_b,
987 UBYTE typ,
988 UBYTE code,
989 UBYTE ttl,
990 UBYTE * ip_header,
991 USHORT identity,
992 ULONG dest_addr,
993 ULONG src_addr,
994 T_desc_list2 * desc_list
995 ) {
996 USHORT chk_sum;
997 UBYTE header_len_b_bak;
998
999 TRACE_FUNCTION ("build_icmp_packet()");
1000
1001 header_len_b_bak = (UBYTE) (header_len_b >> 2);
1002
1003 /* Build ICMP header */
1004
1005 SET_ICMP_TYPE (ip_header, typ, header_len_b);
1006 SET_ICMP_CODE (ip_header, code, header_len_b);
1007 RESET_ICMP_CHK_SUM (ip_header, header_len_b);
1008 chk_sum = desc_checksum (desc_list, header_len_b, 0);
1009 SET_ICMP_CHK_SUM (ip_header, chk_sum, header_len_b);
1010
1011 /* Build IP header */
1012
1013 build_ip_header (
1014 ip_header,
1015 identity,
1016 header_len_b_bak,
1017 NORMAL_SERVICE,
1018 ttl,
1019 src_addr,
1020 dest_addr,
1021 desc_list->list_len,
1022 NO_OFFSET_FRAG,
1023 FLAG_NOT_SET,
1024 FLAG_NOT_SET,
1025 ICMP_PROT
1026 );
1027 }
1028
1029 /*
1030 +-------------------------------------------------------------------+
1031 | PROJECT : WAP MODULE : IP |
1032 | STATE : code ROUTINE : build_icmp_with_payload |
1033 +-------------------------------------------------------------------+
1034 *
1035 * Build a ICMP packet with payload of 64 bits
1036 */
1037 void build_icmp_with_payload (
1038 T_DTI2_DATA_REQ * data_req,
1039 USHORT identity,
1040 UBYTE ttl,
1041 ULONG src_addr,
1042 UBYTE icmp_type,
1043 UBYTE icmp_code
1044 ) {
1045 T_desc2 * desc_new, * desc;
1046 T_desc_list2 * desc_list;
1047 USHORT malloc_len, header_len_b, chk_sum;
1048 UBYTE * ip_header;
1049 ULONG dest_addr;
1050
1051 #define LEN_ICMP_HEADER_PAYLOAD 8
1052 #define LEN_PAYLOAD 8
1053
1054 TRACE_FUNCTION ("build_icmp_with_payload()");
1055
1056 desc_list = & data_req->desc_list2;
1057 desc = (T_desc2 *) desc_list->first;
1058 ip_header = desc->buffer;
1059 dest_addr = GET_IP_SOURCE_ADDR (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1060 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_header);
1061
1062 /* Up to 8 bytes payload of the old datagram */
1063
1064 {
1065 USHORT help = (USHORT) (LEN_PAYLOAD + header_len_b);
1066 if (help < desc->len)
1067 set_desc_len (desc_list, desc, help);
1068 }
1069
1070 /* Throw away the rest descs if there are any */
1071
1072 del_rest_descs (desc_list, desc);
1073
1074 /* Make a new desc for the ICMP packet header */
1075
1076 malloc_len = LEN_ICMP_HEADER_PAYLOAD + LEN_IP_HEADER_B;
1077 make_new_desc (& desc_new, malloc_len, TRUE);
1078
1079 /* Put the desc at the first place of the descs */
1080
1081 put_desc_first_pos (desc_list, desc_new);
1082
1083 /* Build the ICMP packet and the IP header */
1084
1085 ip_header = desc_new->buffer;
1086 header_len_b = LEN_IP_HEADER_B;
1087
1088 SET_ICMP_TYPE (ip_header, icmp_type, header_len_b);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1089 SET_ICMP_CODE (ip_header, icmp_code, header_len_b);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1090 RESET_ICMP_CHK_SUM (ip_header, header_len_b);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1091 chk_sum = desc_checksum (desc_list, header_len_b, 0);
1092 SET_ICMP_CHK_SUM (ip_header, chk_sum, header_len_b);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1093
1094 build_ip_header (
1095 ip_header,
1096 identity,
1097 MIN_HEADER_LEN,
1098 NORMAL_SERVICE,
1099 ttl,
1100 src_addr,
1101 dest_addr,
1102 desc_list->list_len,
1103 NO_OFFSET_FRAG,
1104 FLAG_NOT_SET,
1105 FLAG_NOT_SET,
1106 ICMP_PROT
1107 );
1108 }
1109
1110 /*
1111 +--------------------------------------------------------------------+
1112 | PROJECT : WAP MODULE : IP_KERF |
1113 | STATE : code ROUTINE : init_ip |
1114 +--------------------------------------------------------------------+
1115 *
1116 * Init the global parameter
1117 */
1118 void init_ip (void)
1119 {
1120 T_HILA * p_ul = & ip_data->hila;
1121 T_LOLA * p_dl = & ip_data->lola;
1122 T_KER * p_ker = & ip_data->ker;
1123 USHORT j;
1124
1125 INIT_STATE (HILA, DOWN);
1126 INIT_STATE (LOLA, DOWN);
1127 INIT_STATE (KER, DEACTIVATED);
1128
1129 p_ul->dti_data_req = NULL;
1130 p_ul->drop_packet = FALSE;
1131 p_ul->ttl = STANDARD_TTL;
1132 p_ul->header_len = MIN_HEADER_LEN;
1133 p_ul->state_segment = NO_SEGMENTS;
1134 p_ul->segment_offset = 0;
1135 p_ul->segment_prot = NO_PROT_ID;
1136 p_ul->first_desc_segment = NULL;
1137 p_ul->identity = IDENTITY_0;
1138
1139 p_dl->drop_packet = FALSE;
1140 p_dl->dti_data_ind= NULL;
1141 p_dl->pos_server = 0;
1142
1143 for (j = 0; j < MAX_SEGM_SERVER; j++)
1144 {
1145 p_dl->state_reassembly[j] = NO_SEGMENTS;
1146 p_dl->got_first_segment[j] = FALSE;
1147 p_dl->got_last_segment[j] = FALSE;
1148 p_dl->ip_source_addr_segment[j] = NO_ADDR;
1149 p_dl->data_ind_reassembly[j] = NULL;
1150 p_dl->id_reassemble[j] = NO_ID_REASSBL;
1151 p_dl->prot_reassemble[j] = NO_PROT_REASSBL;
1152 }
1153
1154 p_ker->peer_addr = NO_ADDR;
1155 p_ker->netmask = INIT_NETMASK;
1156 p_ker->source_addr = NO_ADDR;
1157 p_ker->dst_addr = NO_ADDR;
1158
1159 #ifdef _SIMULATION_
1160 p_ker->source_addr = TEST_SRC_ADDR;
1161 p_ker->dst_addr = TEST_DEST_ADDR;
1162 #endif
1163
1164 p_ker->entity_name_hl[0] = 0;
1165 p_ker->entity_name_ll[0] = 0;
1166
1167 p_ker->link_id_ll = IPA_LINK_ID_DEFAULT;
1168 p_ker->link_id_hl = IPA_LINK_ID_DEFAULT;
1169
1170 p_ker->mtu = NO_MTU;
1171 p_ker->icmp_dti_data_req = NULL;
1172 p_ker->send_icmp = FALSE;
1173 }
1174
1175 /*
1176 +--------------------------------------------------------------------+
1177 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
1178 | STATE : code ROUTINE : config_down_ll |
1179 +--------------------------------------------------------------------+
1180 *
1181 * Config down a lower layer entity
1182 */
1183 void config_down_ll (void)
1184 {
1185 T_HILA * p_ul = & ip_data->hila;
1186 T_LOLA * p_dl = & ip_data->lola;
1187 T_KER * p_ker = & ip_data->ker;
1188
1189 USHORT j;
1190
1191 TRACE_FUNCTION ("config_down_ll()");
1192
1193 free_primitive_data_ind (& p_dl->dti_data_ind);
1194 free_primitive_data_req (& p_ker->icmp_dti_data_req);
1195
1196 for (j = 0; j < MAX_SEGM_SERVER; j++)
1197 {
1198 /* free_primitive_data_ind (p_dl->data_ind_reassembly + j); */
1199 /* Has already been freed five lines above, */
1200 /* because p_dl->dti_data_ind == p_dl->data_ind_reassembly. */
1201 /* Please think anew when MAX_SEGM_SERVER becomes != 1. */
1202
1203 csf_stop_timer (j);
1204 p_dl->timer_reass_running[j] = FALSE;
1205
1206 p_dl->state_reassembly[j] = NO_SEGMENTS;
1207 p_dl->got_first_segment[j] = FALSE;
1208 p_dl->got_last_segment[j] = FALSE;
1209 p_dl->ip_source_addr_segment[j] = NO_ADDR;
1210 p_dl->data_ind_reassembly[j] = NULL;
1211 p_dl->id_reassemble[j] = NO_ID_REASSBL;
1212 p_dl->prot_reassemble[j] = NO_PROT_REASSBL;
1213 }
1214
1215 /* Keep STATE_WAIT are stored even if config down
1216 * send READY_IND and set HILA STATE to IDLE if */
1217
1218 switch (GET_STATE (HILA)) {
1219 case WAIT: /* Keep state */
1220 break;
1221 case SEND: /* Send ready indication */
1222 dti_start (
1223 ip_hDTI,
1224 IP_DTI_DEF_INSTANCE,
1225 IP_DTI_HL_INTERFACE,
1226 IP_DTI_DEF_CHANNEL
1227 );
1228 default:
1229 SET_STATE (HILA, IDLE);
1230 break;
1231 }
1232 SET_STATE (HILA, IDLE)
1233
1234 p_ul->drop_packet = FALSE;
1235 p_ul->state_segment = NO_SEGMENTS;
1236 p_ul->header_len = MIN_HEADER_LEN;
1237 p_ul->ttl = STANDARD_TTL;
1238 p_ul->segment_prot = NO_PROT_ID;
1239 p_ul->segment_offset = 0;
1240 p_ul->first_desc_segment = NULL;
1241
1242 /* Be sure that STATE_WAIT are stored even if config down */
1243
1244 if (GET_STATE (LOLA) NEQ WAIT)
1245 SET_STATE (LOLA, IDLE)
1246 p_dl->drop_packet = FALSE;
1247
1248 p_dl->pos_server = 0;
1249
1250 p_ker->peer_addr = NO_ADDR;
1251 p_ker->netmask = INIT_NETMASK;
1252 p_ker->source_addr = NO_ADDR;
1253 p_ker->dst_addr = NO_ADDR;
1254 p_ker->entity_name_ll[0] = 0;
1255 p_ker->mtu = NO_MTU;
1256 p_ker->send_icmp = FALSE;
1257 }
1258
1259 /*
1260 +--------------------------------------------------------------------+
1261 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
1262 | Sp_TATE : code ROUTINE : terminate_ip |
1263 +--------------------------------------------------------------------+
1264 *
1265 * Handle global parameter by terminate
1266 */
1267 void terminate_ip (void)
1268 {
1269 TRACE_FUNCTION ("terminate_ip()");
1270
1271 /* Shutdown lower entity interface */
1272 config_down_ll ();
1273
1274 /* Parameter for higher layer entity */
1275 ip_data->ker.entity_name_hl[0] = 0;
1276 }
1277
1278 /*
1279 +--------------------------------------------------------------------+
1280 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
1281 | STATE : code ROUTINE : ip_addr_int_to_byte |
1282 +--------------------------------------------------------------------+
1283 *
1284 * Build the IP address in ULONG to 4 bytes
1285 */
1286 void ip_addr_int_to_byte (UBYTE * b_values, ULONG ul_value)
1287 {
1288 TRACE_FUNCTION ("int_to_byte()");
1289
1290 b_values[3] = (UBYTE) (ul_value);
1291 b_values[2] = (UBYTE) (ul_value>>8);
1292 b_values[1] = (UBYTE) (ul_value>>16);
1293 b_values[0] = (UBYTE) (ul_value>>24);
1294 }
1295
1296 /*
1297 +--------------------------------------------------------------------+
1298 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
1299 | STATE : code ROUTINE : chk_packet_len |
1300 +--------------------------------------------------------------------+
1301 *
1302 * Check the IP packet length
1303 */
1304 UBYTE chk_packet_len (UBYTE * ip_header, T_desc_list2 * desc_list)
1305 {
1306 USHORT total_len, chk_len, mtu_len;
1307
1308 TRACE_FUNCTION ("chk_packet_len()");
1309
1310 /* This is the calculated length */
1311 total_len = desc_list->list_len;
1312
1313 /* This is the length indicated in the IP header */
1314 chk_len = (USHORT) GET_IP_TOTAL_LEN (ip_header);
1315
1316 /* This is the max defined packet length */
1317 mtu_len = ip_data->ker.mtu;
1318
1319 if (
1320 (chk_len < MIN_HEADER_LEN) OR (chk_len > total_len) OR
1321 (total_len < MIN_HEADER_LEN) OR (chk_len > mtu_len)
1322 )
1323 return ERR_PACKET_LEN;
1324 else if (chk_len < total_len)
1325 return CHANGE_PACKET_LEN;
1326 else
1327 return NO_ERROR;
1328 }
1329
1330 /*
1331 +--------------------------------------------------------------------+
1332 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
1333 | STATE : code ROUTINE : build_ip_packet |
1334 +--------------------------------------------------------------------+
1335 *
1336 * Build the datagram or packets before sending
1337 */
1338 void build_ip_packet (BOOL uplink, UBYTE select)
1339 {
1340 UBYTE * ip_header;
1341 USHORT total_len;
1342 ULONG dest_addr, src_addr;
1343 T_desc_list2 * desc_list;
1344 T_desc2 * desc;
1345 T_HILA * p_ul = & ip_data->hila;
1346 T_LOLA * p_dl = & ip_data->lola;
1347 T_KER * p_ker = & ip_data->ker;
1348
1349 T_DTI2_DATA_REQ * data_req;
1350 T_DTI2_DATA_IND * data_ind;
1351
1352 TRACE_FUNCTION ("build_ip_packet()");
1353
1354 src_addr = p_ker->source_addr;
1355
1356 /* Build uplink packets */
1357
1358 if (uplink)
1359 {
1360 data_req = p_ul->dti_data_req;
1361
1362 switch (select) {
1363 /* Build "standard" IP packet */
1364 case B_NORMAL_PACKET:
1365
1366 desc_list = & p_ul->dti_data_req->desc_list2;
1367 total_len = desc_list->list_len;
1368 desc = (T_desc2 *) desc_list->first;
1369 ip_header = desc->buffer;
1370 dest_addr = GET_IP_DEST_ADDR (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1371
1372 build_ip_header (
1373 ip_header,
1374 p_ul->identity,
1375 (UBYTE) p_ul->header_len,
1376 NORMAL_SERVICE,
1377 p_ul->ttl,
1378 src_addr,
1379 dest_addr,
1380 total_len,
1381 NO_OFFSET_FRAG,
1382 FLAG_NOT_SET,
1383 FLAG_NOT_SET,
1384 UDP_PROT
1385 );
1386 #ifndef _SIMULATION_
1387 p_ul->identity++;
1388 #endif
1389 break;
1390
1391 /* Build IP header for ICMP messages. Note only ICMP from higher layer. */
1392 case B_ICMP_PACKET:
1393
1394 desc_list = & p_ul->dti_data_req->desc_list2;
1395 total_len = desc_list->list_len;
1396 desc = (T_desc2 *) desc_list->first;
1397 ip_header = desc->buffer;
1398 dest_addr = GET_IP_DEST_ADDR (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1399
1400 build_ip_header (
1401 ip_header,
1402 p_ul->identity,
1403 (UBYTE) p_ul->header_len,
1404 NORMAL_SERVICE,
1405 p_ul->ttl,
1406 src_addr,
1407 dest_addr,
1408 total_len,
1409 NO_OFFSET_FRAG,
1410 FLAG_NOT_SET,
1411 FLAG_NOT_SET,
1412 ICMP_PROT
1413 );
1414 #ifndef _SIMULATION_
1415 p_ul->identity++;
1416 #endif
1417 break;
1418
1419 /* Build fragments. The first fragment use the original header from HL. */
1420 case B_SEGMENT:
1421 {
1422 /* Check if it is the first fragment */
1423
1424 if (p_ul->state_segment EQ NO_SEGMENTS)
1425 {
1426 T_desc2 * desc_new;
1427 USHORT pos_copy, total_len_copy, malloc_len, header_len_b;
1428
1429 desc_list = & p_ul->dti_data_req->desc_list2;
1430 total_len = desc_list->list_len;
1431 desc = (T_desc2 *) desc_list->first;
1432 ip_header = desc->buffer;
1433 dest_addr = GET_IP_DEST_ADDR (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1434 src_addr = p_ker->source_addr;
1435 p_ul->header_len = (USHORT) GET_IP_HEADER_LEN (ip_header);
1436 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_header);
1437
1438 p_ul->state_segment = SEND_SEGMENT;
1439 p_ul->sended_segment_len = p_ker->mtu;
1440 p_ul->list_len_segment = total_len;
1441 p_ul->segment_prot = GET_IP_PROT (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1442 p_ul->first_desc_segment = desc;
1443 dest_addr = GET_IP_DEST_ADDR (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1444
1445 /* Make a new desc for the fragment */
1446
1447 malloc_len = p_ker->mtu;
1448 make_new_desc (& desc_new, malloc_len, FALSE);
1449
1450 data_req->desc_list2.first = (ULONG) desc_new;
1451 data_req->desc_list2.list_len = malloc_len;
1452 desc_new->next = 0;
1453
1454 /* Build the first fragment */
1455 copy_from_descs_to_desc (
1456 & desc, desc_new, malloc_len, 0, 0, & pos_copy, & total_len_copy
1457 );
1458 if (total_len_copy NEQ malloc_len)
1459 {
1460 /* Corrupted packet -> drop it */
1461 p_ul->drop_packet = TRUE;
1462
1463 /* Clean up and free the descs */
1464 del_descs (p_ul->first_desc_segment);
1465 p_ul->segment_offset = 0;
1466 p_ul->next_segment_desc = 0;
1467 p_ul->last_segment_pos = 0;
1468 p_ul->sended_segment_len = 0;
1469 p_ul->state_segment = NO_SEGMENTS;
1470 }
1471 else
1472 {
1473 p_ul->segment_id = p_ul->identity;
1474 p_ul->segment_offset = 0;
1475
1476 build_ip_header (
1477 desc_new->buffer,
1478 p_ul->segment_id,
1479 (UBYTE) p_ul->header_len,
1480 NORMAL_SERVICE,
1481 p_ul->ttl,
1482 src_addr,
1483 dest_addr,
1484 malloc_len,
1485 (USHORT) (p_ul->segment_offset >> 3),
1486 FLAG_NOT_SET,
1487 FLAG_SET,
1488 p_ul->segment_prot
1489 );
1490 #ifndef _SIMULATION_
1491 p_ul->identity++;
1492 #endif
1493
1494 /* For the next fragment */
1495 p_ul->segment_offset = (USHORT) (malloc_len - header_len_b);
1496 p_ul->next_segment_desc = (ULONG) desc;
1497 p_ul->last_segment_pos = pos_copy;
1498 }
1499 }
1500
1501 /* Middle fragment */
1502
1503 else if (p_ul->sended_segment_len + p_ker->mtu <
1504 p_ul->list_len_segment + LEN_IP_HEADER_B)
1505 {
1506 T_desc2 * desc_new;
1507
1508 USHORT pos_copy, total_len_copy, malloc_len;
1509
1510 /* Make a new primitive for the fragment */
1511
1512 PALLOC (dti_data_req, DTI2_DATA_REQ);
1513 p_ul->dti_data_req = dti_data_req;
1514
1515 /* Malloc the fragment desc */
1516
1517 malloc_len = p_ker->mtu;
1518 make_new_desc (& desc_new, malloc_len, FALSE);
1519
1520 dti_data_req->desc_list2.first = (ULONG) desc_new;
1521 dti_data_req->desc_list2.list_len = malloc_len;
1522 desc_new->next = 0;
1523
1524 /* Copy the data into the fragment desc */
1525
1526 desc = (T_desc2 *) p_ul->next_segment_desc;
1527 copy_from_descs_to_desc (
1528 & desc,
1529 desc_new,
1530 (USHORT) (malloc_len - LEN_IP_HEADER_B),
1531 p_ul->last_segment_pos,
1532 LEN_IP_HEADER_B,
1533 & pos_copy,
1534 & total_len_copy
1535 );
1536
1537 if (total_len_copy NEQ malloc_len - LEN_IP_HEADER_B)
1538 {
1539 /* Corrupted packet -> drop it */
1540 p_ul->drop_packet = TRUE;
1541
1542 /* Clean up and free the descs */
1543 del_descs (p_ul->first_desc_segment);
1544 p_ul->segment_offset = 0;
1545 p_ul->next_segment_desc = 0;
1546 p_ul->last_segment_pos = 0;
1547 p_ul->sended_segment_len = 0;
1548 p_ul->state_segment = NO_SEGMENTS;
1549 }
1550 else
1551 {
1552 /* Build the IP fragment */
1553
1554 UBYTE * ip_header_first = p_ul->first_desc_segment->buffer;
1555 dest_addr = GET_IP_DEST_ADDR (ip_header_first);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1556
1557 build_ip_header (
1558 desc_new->buffer,
1559 p_ul->segment_id,
1560 MIN_HEADER_LEN,
1561 NORMAL_SERVICE,
1562 p_ul->ttl,
1563 src_addr,
1564 dest_addr,
1565 malloc_len,
1566 (USHORT) (p_ul->segment_offset >> 3),
1567 FLAG_NOT_SET,
1568 FLAG_SET,
1569 p_ul->segment_prot
1570 );
1571
1572 /* For the next fragment */
1573 p_ul->segment_offset = (USHORT)
1574 (p_ul->segment_offset + malloc_len - LEN_IP_HEADER_B);
1575 p_ul->next_segment_desc = (ULONG) desc;
1576 p_ul->last_segment_pos = pos_copy;
1577 p_ul->sended_segment_len = (USHORT)
1578 (p_ul->sended_segment_len + malloc_len - LEN_IP_HEADER_B);
1579 }
1580 }
1581 else /* Last fragment */
1582 {
1583 T_desc2 * desc_new;
1584
1585 USHORT pos_copy, total_len_copy, malloc_len;
1586
1587 /* Make a new primitive for the fragment */
1588
1589 PALLOC (dti_data_req, DTI2_DATA_REQ);
1590 p_ul->dti_data_req = dti_data_req;
1591
1592 /* Calculate the correct len for fragment desc and malloc */
1593
1594 malloc_len = (USHORT) (LEN_IP_HEADER_B +
1595 p_ul->list_len_segment - p_ul->sended_segment_len);
1596 make_new_desc (& desc_new, malloc_len, FALSE);
1597
1598 dti_data_req->desc_list2.first = (ULONG) desc_new;
1599 dti_data_req->desc_list2.list_len = malloc_len;
1600 desc_new->next = 0;
1601
1602 /* Copy the data into the fragment desc */
1603
1604 desc = (T_desc2 *) p_ul->next_segment_desc;
1605
1606 copy_from_descs_to_desc (
1607 & desc,
1608 desc_new,
1609 (USHORT) (malloc_len - LEN_IP_HEADER_B),
1610 p_ul->last_segment_pos,
1611 LEN_IP_HEADER_B,
1612 & pos_copy,
1613 & total_len_copy
1614 );
1615
1616 if (total_len_copy NEQ malloc_len - LEN_IP_HEADER_B)
1617 {
1618 /* Corrupted packet -> drop it */
1619 p_ul->drop_packet = TRUE;
1620
1621 /* Clean up and free the descs */
1622 del_descs (p_ul->first_desc_segment);
1623 p_ul->segment_offset = 0;
1624 p_ul->next_segment_desc = 0;
1625 p_ul->last_segment_pos = 0;
1626 p_ul->sended_segment_len = 0;
1627 p_ul->state_segment = NO_SEGMENTS;
1628 }
1629 else
1630 {
1631 /* Build the fragment header */
1632
1633 UBYTE * ip_header_first = p_ul->first_desc_segment->buffer;
1634 dest_addr = GET_IP_DEST_ADDR (ip_header_first);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1635
1636 build_ip_header (
1637 desc_new->buffer,
1638 p_ul->segment_id,
1639 MIN_HEADER_LEN,
1640 NORMAL_SERVICE,
1641 p_ul->ttl,
1642 src_addr,
1643 dest_addr,
1644 malloc_len,
1645 (USHORT) (p_ul->segment_offset >> 3),
1646 FLAG_NOT_SET,
1647 FLAG_NOT_SET,
1648 p_ul->segment_prot
1649 );
1650
1651 /* Clean up and free the descs */
1652
1653 del_descs (p_ul->first_desc_segment);
1654
1655 p_ul->segment_offset = 0;
1656 p_ul->next_segment_desc = 0;
1657 p_ul->last_segment_pos = 0;
1658 p_ul->sended_segment_len = 0;
1659 p_ul->state_segment = NO_SEGMENTS;
1660 }
1661 }
1662 }
1663 break;
1664
1665 default:
1666 break;
1667 }
1668 }
1669 else
1670 {
1671 data_ind = p_dl->dti_data_ind;
1672
1673 /* Compute DL packets */
1674
1675 switch (select) {
1676 /* Ping request */
1677 case B_ICMP_ECHO_REPLY:
1678 {
1679 USHORT header_len_b;
1680
1681 PPASS (data_ind, data_request, DTI2_DATA_REQ);
1682 desc_list = & data_request->desc_list2;
1683 desc = (T_desc2 *) desc_list->first;
1684 ip_header = desc->buffer;
1685 header_len_b = (USHORT) GET_IP_HEADER_LEN_B (ip_header);
1686
1687 dest_addr = GET_IP_SOURCE_ADDR (ip_header);/*lint !e415 !e416 (Warning -- access/creation of out-of-bounds pointer) */
1688
1689 build_icmp_packet (
1690 (UBYTE) header_len_b,
1691 ICMP_TYP_ECHO_REPLY,
1692 ICMP_CODE_ECHO_REPLY,
1693 p_ul->ttl,
1694 ip_header,
1695 p_ul->identity,
1696 dest_addr,
1697 src_addr,
1698 desc_list
1699 );
1700 #ifndef _SIMULATION_
1701 p_ul->identity++;
1702 #endif
1703 p_ker->icmp_dti_data_req = data_request;
1704 }
1705 break;
1706
1707 case B_ICMP_REASSEMBLE_TIMEOUT:
1708 {
1709 /* Datagram for ICMP - reassembly - message */
1710
1711 data_ind = p_dl->data_ind_reassembly[p_dl->pos_server];
1712
1713 {
1714 PPASS (data_ind, data_request, DTI2_DATA_REQ);
1715
1716 build_icmp_with_payload (
1717 data_request,
1718 p_ul->identity,
1719 p_ul->ttl,
1720 p_ker->source_addr,
1721 ICMP_TYP_TIME_EXCEDED,
1722 ICMP_CODE_FRAGM_TIME_EXC
1723 );
1724 #ifndef _SIMULATION_
1725 p_ul->identity++;
1726 #endif
1727 p_ker->icmp_dti_data_req = data_request;
1728 }
1729 }
1730 break;
1731
1732 case B_ICMP_NO_FORWARD:
1733 {
1734 /* No destination address - build ICMP frame */
1735
1736 PPASS (data_ind, data_request, DTI2_DATA_REQ);
1737
1738 build_icmp_with_payload (
1739 data_request,
1740 p_ul->identity,
1741 p_ul->ttl,
1742 p_ker->source_addr,
1743 ICMP_TYP_DEST_URECHBL,
1744 ICMP_CODE_NO_HOST
1745 );
1746 #ifndef _SIMULATION_
1747 p_ul->identity++;
1748 #endif
1749 p_ker->icmp_dti_data_req = data_request;
1750 }
1751 break;
1752
1753 default:
1754 break;
1755 }
1756 }
1757 }
1758
1759 /*
1760 +--------------------------------------------------------------------+
1761 | PROJECT : GSM-FaD (8444) MODULE : IP_KERF |
1762 | STATE : code ROUTINE : check_ip_address |
1763 +--------------------------------------------------------------------+
1764 *
1765 * Check the IP address
1766 */
1767 void check_ip_address (
1768 BOOL * addr_type_dest,
1769 BOOL * addr_type_src,
1770 ULONG dest_addr,
1771 ULONG src_addr
1772 ) {
1773 UBYTE i;
1774 UBYTE b_dest_addr[4], b_src_addr[4], first_nibbl_dest, first_nibbl_src;
1775
1776 #define BCAST 0xFF
1777 #define LOOP_BACK 0x7F
1778 #define DEFAULT_ROUTE 0
1779 #define CLASS_A 0x0
1780 #define CLASS_B 0x2
1781 #define CLASS_C 0x6
1782 #define MULTICAST 0xE
1783 #define CLASS_E 0xF
1784 #define M_CAST_FF 0xFFFFFFFF
1785
1786 TRACE_FUNCTION ("check_ip_address()");
1787
1788 ip_addr_int_to_byte (b_dest_addr, dest_addr);
1789 ip_addr_int_to_byte (b_src_addr, src_addr);
1790
1791 first_nibbl_dest = (UBYTE) (b_dest_addr[0] >> 4);
1792 first_nibbl_src = (UBYTE) (b_src_addr[0] >> 4);
1793
1794 for (i=0; i < MAX_ADDR_TYPES; i++)
1795 {
1796 addr_type_dest[i] = FALSE;
1797 addr_type_src[i] = FALSE;
1798 }
1799
1800 /* Check if broadcast address */
1801
1802 if (dest_addr EQ M_CAST_FF)
1803 addr_type_dest[BCAST_ADDR_255] = TRUE;
1804
1805 if (src_addr EQ M_CAST_FF)
1806 addr_type_src[BCAST_ADDR_255] = TRUE;
1807
1808 /* Correct destination address? */
1809
1810 if (dest_addr NEQ src_addr)
1811 {
1812 addr_type_dest[NO_DEST_ADDR] = TRUE;
1813 addr_type_src[NO_DEST_ADDR] = TRUE;
1814 }
1815
1816 /* Loop-back address? */
1817
1818 if (b_dest_addr[0] EQ LOOP_BACK)
1819 addr_type_dest[LOOP_BACK_ADDR] = TRUE;
1820
1821 if (b_src_addr[0] EQ LOOP_BACK)
1822 addr_type_src[LOOP_BACK_ADDR] = TRUE;
1823
1824 /* Check kind of class */
1825
1826 if ((first_nibbl_src >> 3) EQ CLASS_A)
1827 addr_type_src[CLASS_A_ADDR] = TRUE;
1828
1829 if ((first_nibbl_dest >> 3) EQ CLASS_A)
1830 addr_type_dest[CLASS_A_ADDR] = TRUE;
1831
1832 if ((first_nibbl_src >> 2) EQ CLASS_B)
1833 addr_type_src[CLASS_B_ADDR] = TRUE;
1834
1835 if ((first_nibbl_dest >> 2) EQ CLASS_B)
1836 addr_type_dest[CLASS_B_ADDR] = TRUE;
1837
1838 if ((first_nibbl_src >> 1) EQ CLASS_C)
1839 addr_type_src[CLASS_C_ADDR] = TRUE;
1840
1841 if ((first_nibbl_dest >> 1) EQ CLASS_C)
1842 addr_type_dest[CLASS_C_ADDR] = TRUE;
1843
1844 if (first_nibbl_src EQ CLASS_E AND dest_addr NEQ M_CAST_FF)
1845 addr_type_src[CLASS_E_ADDR] = TRUE;
1846
1847 if (first_nibbl_dest EQ CLASS_E AND src_addr NEQ M_CAST_FF)
1848 addr_type_dest[CLASS_E_ADDR] = TRUE;
1849
1850 /* Multicast or class D */
1851
1852 if (first_nibbl_dest EQ MULTICAST)
1853 addr_type_dest[MCAST_ADDR] = TRUE;
1854
1855 if (first_nibbl_src EQ MULTICAST)
1856 addr_type_src[MCAST_ADDR] = TRUE;
1857
1858 /* Default route */
1859
1860 if (dest_addr EQ DEFAULT_ROUTE)
1861 addr_type_dest[DEFAULT_R_ADDR] = TRUE;
1862
1863 if (src_addr EQ DEFAULT_ROUTE)
1864 addr_type_src[DEFAULT_R_ADDR] = TRUE;
1865
1866 /* Bad address? */
1867
1868 if (
1869 addr_type_src[BCAST_ADDR_255] OR
1870 addr_type_src[LOOP_BACK_ADDR] OR
1871 addr_type_src[DEFAULT_R_ADDR]
1872 ) {
1873 addr_type_src[BAD_UL_SRC_ADDR] = TRUE;
1874 addr_type_src[BAD_DL_SRC_ADDR] = TRUE;
1875 }
1876
1877 if (
1878 addr_type_dest[BCAST_ADDR_255] OR
1879 addr_type_dest[LOOP_BACK_ADDR] OR
1880 addr_type_dest[DEFAULT_R_ADDR]
1881 ) {
1882 addr_type_dest[BAD_UL_DEST_ADDR] = TRUE;
1883 addr_type_dest[BAD_DL_DEST_ADDR] = TRUE;
1884 }
1885 }
1886
1887 /* Internet checksum calculations as needed in IP and UDP.
1888 * See RFC 1071 for details.
1889 *
1890 * USHORT inet_checksum (UBYTE * block, USHORT len)
1891 * Computes the Internet checksum over a simple data block.
1892 *
1893 * USHORT desc_checksum (
1894 * T_desc_list2 * dlist,
1895 * USHORT start_offset,
1896 * ULONG start_value
1897 * )
1898 * Computes the Internet checksum over a DTI descriptor list,
1899 * beginning at start_offset and with start_value. */
1900
1901 #define LITTLE_ENDIAN /* Change this for big-endian mode. */
1902
1903 /** Computes the Internet checksum [RFC 1071] over a simple data block.
1904 *
1905 * @param block pointer to data block
1906 * @param len length of the block in octets
1907 * @return the checksum
1908 */
1909 USHORT inet_checksum (UBYTE * block, USHORT len)
1910 {
1911 BOOL have_leftover = len % 2; /* If non-zero, there is a leftover
1912 * octet at the end of the (odd-sized)
1913 * data block. */
1914 ULONG value; /* Value to add. (Since we know
1915 * nothing about the alignment of the
1916 * block, we can't read the USHORTs
1917 * directly from the block.) */
1918 ULONG checksum = 0; /* Checksum accumulator. */
1919
1920 len >>= 1; /* Count words now, not octets. */
1921
1922 while (len--)
1923 {
1924 /* Because we must read the data bytewise, we cannot profit from
1925 * the independency of endianness of the original algorithm.
1926 * That means that we have to make two different cases for big
1927 * endian and little endian. */
1928
1929 #if defined LITTLE_ENDIAN
1930 /*lint -e{661} (Warning -- access of out-of-bounds pointer) */
1931 value = block[1]<<8 | block[0];
1932 #elif defined BIG_ENDIAN
1933 /*lint -e{662} (Warning -- creation of out-of-bounds pointer) */
1934 value = block[0]<<8 | block[1];
1935 #else
1936 #error "LITTLE_ENDIAN or BIG_ENDIAN must be defined."
1937 #endif
1938
1939 checksum += value;
1940 /*lint -e{662} (Warning -- creation of out-of-bounds pointer) */
1941 block +=2;
1942 }
1943
1944 if (have_leftover)
1945 /*lint -e{661} (Warning -- access of out-of-bounds pointer) */
1946 checksum += *block;
1947
1948 /* Fold into 16 bits. */
1949 while (checksum >> 16)
1950 checksum = (checksum & 0xffff) + (checksum >> 16);
1951
1952 return (USHORT) ~checksum;
1953 }
1954
1955 /** Computes a part of an Internet checksum over a data block. A
1956 * leftover octet from a previous partial calculation is taken into
1957 * account. If an octet is left over, it is returned as well as the
1958 * fact that there is a leftover octet. This function is intended to
1959 * be called only by desc_checksum() and partial_checksum().
1960 *
1961 * @param block pointer to data block
1962 * @param len length of the block in octets
1963 * @param sum checksum value to begin with
1964 * @param have_leftover_ptr if non-zero, a leftover octet is in *leftover_ptr
1965 * @param leftover_ptr pointer to leftover octet; valid on input and
1966 * output iff *have_leftover_ptr
1967 * @return the part of the sum calculated
1968 */
1969 static ULONG checksum_block_part (
1970 UBYTE * block,
1971 USHORT len,
1972 ULONG sum,
1973 BOOL * have_leftover_ptr,
1974 UBYTE * leftover_ptr
1975 ) {
1976 /* This function is as complicated as it is for two reasons:
1977 *
1978 * (a) Each block may have an even or odd number of octets. Because
1979 * this checksum is 16-bit based, an octet may be left over from the
1980 * previous calculation and must be taken into account. Also in this
1981 * calculation an octet may be left over. This fact and the value of
1982 * the octet must be made known to the caller.
1983 *
1984 * (b) We must not make any assumptions about the alignment of the
1985 * block. Therefore, in order not to cause alignment problems, all
1986 * 16-bit values must be read bytewise. */
1987
1988 ULONG value; /* 16-bit value to be summed up */
1989
1990 TRACE_FUNCTION ("checksum_block_part()");
1991
1992 /* Previous calculation may have left over an octet. */
1993 if (*have_leftover_ptr)
1994 {
1995 if (len == 0)
1996 return sum;
1997
1998 /* See comment in inet_checksum() above for an explanation. */
1999
2000 #if defined LITTLE_ENDIAN
2001 value = (*block++ << 8) | *leftover_ptr;
2002 #elif defined BIG_ENDIAN
2003 value = (*leftover_ptr << 8) | *block++;
2004 #else
2005 #error "LITTLE_ENDIAN or BIG_ENDIAN must be defined."
2006 #endif
2007
2008 len--;
2009 sum += value;
2010 }
2011
2012 /* Main loop over word values. */
2013 *have_leftover_ptr = len % 2;
2014 len >>= 1;
2015 while (len--)
2016 {
2017 /* See comment in inet_checksum() above for an explanation. */
2018
2019 #if defined LITTLE_ENDIAN
2020 value = block[1]<<8 | block[0];
2021 #elif defined BIG_ENDIAN
2022 value = block[0]<<8 | block[1];
2023 #else
2024 #error "LITTLE_ENDIAN or BIG_ENDIAN must be defined."
2025 #endif
2026
2027 sum += value;
2028 block +=2;
2029 }
2030
2031 /* Check for leftover octet. */
2032 if (*have_leftover_ptr)
2033 *leftover_ptr = *block;
2034
2035 return sum;
2036 }
2037
2038 /** Compute a partial Internet checksum to be used as a astart_value
2039 * for desc_checksum. The block must have even length.
2040 *
2041 * @param block data block to compute the checksum over
2042 * @param len length of the block
2043 * @return the partial sum calculated
2044 */
2045 ULONG partial_checksum (UBYTE * block, USHORT len)
2046 {
2047 BOOL dummy1 = 0; /* Needed to call checksum_block_part(). */
2048 UBYTE dummy2 = 0;
2049
2050 return checksum_block_part (block, len, 0, & dummy1, & dummy2);
2051 }
2052
2053 /** Computes the Internet checksum over a DTI descriptor list. There
2054 * may be a value from a previous partial calculation that is added to
2055 * the sum as a start value. The function relies on the data length
2056 * being at least start_offset.
2057 *
2058 * @param dlist descriptor list containing the data
2059 * @param start_offset beginning position of interesting data
2060 * @param start_value value from previous partial checksum calculation
2061 * @return the checksum value
2062 */
2063 USHORT desc_checksum (
2064 T_desc_list2 * dlist,
2065 USHORT start_offset,
2066 ULONG start_value
2067 ) {
2068 ULONG checksum = start_value; /* The checksum to be calculated. */
2069 T_desc2 * desc_p; /* Pointer to current descriptor. */
2070 BOOL have_leftover = 0; /* True iff we have a leftover octet
2071 * from the previous partial sum. */
2072 UBYTE leftover_octet = 0; /* An octet left over from the
2073 * previous partial sum. */
2074
2075 TRACE_FUNCTION ("desc_checksum()");
2076
2077 /* Calculating the sum of the first buffer, we have to take the
2078 * start offset into account. This includes finding the descriptor
2079 * the offset lies in. */
2080
2081 desc_p = (T_desc2 *) dlist->first;
2082 while (start_offset > desc_p->len)
2083 {
2084 start_offset = (USHORT) (start_offset - desc_p->len);
2085 desc_p = (T_desc2 *) desc_p->next;
2086 }
2087 checksum = checksum_block_part (
2088 desc_p->buffer + start_offset,
2089 (USHORT) (desc_p->len - start_offset),
2090 checksum,
2091 & have_leftover,
2092 & leftover_octet
2093 );
2094
2095 /* Now loop over the other descriptors. */
2096 for (
2097 desc_p = (T_desc2 *) desc_p->next;
2098 desc_p != 0;
2099 desc_p = (T_desc2 *) desc_p->next
2100 ) {
2101 checksum = checksum_block_part (
2102 desc_p->buffer,
2103 desc_p->len,
2104 checksum,
2105 & have_leftover,
2106 & leftover_octet
2107 );
2108 }
2109
2110 if (have_leftover)
2111 checksum += leftover_octet;
2112
2113 /* Fold into 16 bits. */
2114 while (checksum >> 16)
2115 checksum = (checksum & 0xffff) + (checksum >> 16);
2116
2117 return (USHORT) ~checksum;
2118 }
2119
2120 /*-------------------------------------------------------------------------*/
2121