FreeCalypso > hg > fc-tourmaline
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 |