1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Component */
17 /** */
18 /** Internet Protocol (IP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25
26
27 /* Include necessary system files. */
28
29 #include "nx_api.h"
30 #include "nx_ip.h"
31 #include "nx_ipv6.h"
32 #include "nx_icmp.h"
33 #include "nx_packet.h"
34
35
36 #ifdef NX_IPSEC_ENABLE
37 #include "nx_ipsec.h"
38 #endif
39
40
41 /**************************************************************************/
42 /* */
43 /* FUNCTION RELEASE */
44 /* */
45 /* _nx_ip_dispatch_process PORTABLE C */
46 /* 6.1.9 */
47 /* AUTHOR */
48 /* */
49 /* Yuxin Zhou, Microsoft Corporation */
50 /* */
51 /* DESCRIPTION */
52 /* */
53 /* This function goes through IP header and option fields, and */
54 /* dispatches into various process routines depending on the header */
55 /* options. */
56 /* */
57 /* INPUT */
58 /* */
59 /* ip_ptr Pointer to IP instance */
60 /* packet_ptr Incoming IP packet */
61 /* protocol The first protocol immediately*/
62 /* following IP header */
63 /* */
64 /* OUTPUT */
65 /* */
66 /* Status 0: do not drop packet */
67 /* 1: drop packet */
68 /* */
69 /* CALLS */
70 /* */
71 /* [nx_ip_icmpv6_packet_process] ICMPv6 header process */
72 /* [nx_ip_tcp_packet_receive] TCP packet process */
73 /* [nx_ip_udp_packet_receive] UDP packet process */
74 /* ICMP ping request */
75 /* _nx_ipv6_process_hop_by_hop_option IPv6 hop by hop option */
76 /* process */
77 /* NX_ICMPV6_SEND_PARAMETER_PROBELM Send ICMP parameter problem */
78 /* _nx_ipv6_process_routing_option IPv6 routing option process */
79 /* _nx_ipv6_process_fragment_option IPv6 fragment option process */
80 /* [nx_ipsec_authentication_header_receive] */
81 /* IPSec authentication header */
82 /* process */
83 /* [nx_ipsec_encapsulating_security_payload_receive */
84 /* IPSec encapsulating security */
85 /* payload process */
86 /* (ip_icmp_packet_receive) Receive a ICMP packet */
87 /* (ip_igmp_packet_receive) Receive a IGMP packet */
88 /* */
89 /* CALLED BY */
90 /* */
91 /* Application Code */
92 /* */
93 /* RELEASE HISTORY */
94 /* */
95 /* DATE NAME DESCRIPTION */
96 /* */
97 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
98 /* 09-30-2020 Yuxin Zhou Modified comment(s), fixed */
99 /* destination header check, */
100 /* resulting in version 6.1 */
101 /* 10-15-2021 Yuxin Zhou Modified comment(s), expanded */
102 /* protocols support for raw */
103 /* packet, */
104 /* resulting in version 6.1.9 */
105 /* */
106 /**************************************************************************/
_nx_ip_dispatch_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT protocol)107 UINT _nx_ip_dispatch_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT protocol)
108 {
109
110 UINT drop_packet;
111
112 #ifdef FEATURE_NX_IPV6
113 NXD_IPV6_ADDRESS *incoming_addr;
114 UINT next_option_offset;
115
116 #ifndef NX_DISABLE_ICMPV6_ERROR_MESSAGE
117 UINT nx_packet_option_offset;
118 #endif /* NX_DISABLE_ICMPV6_ERROR_MESSAGE */
119 #endif /* FEATURE_NX_IPV6 */
120
121 #ifdef NX_IPSEC_ENABLE
122 UINT ret;
123 ULONG next_protocol = 0;
124 NXD_ADDRESS src_addr, dest_addr;
125 #ifndef NX_DISABLE_IPV4
126 NX_IPV4_HEADER *ipv4_header;
127 #endif /* NX_DISABLE_IPV4 */
128 #ifdef FEATURE_NX_IPV6
129 NX_IPV6_HEADER *ipv6_header;
130 NX_ICMPV6_HEADER *icmp_header_ptr;
131 #endif /* FEATURE_NX_IPV6 */
132 #endif /* NX_IPSEC_ENABLE */
133
134
135 /* Initialize local variables. */
136 drop_packet = 0;
137 #ifdef FEATURE_NX_IPV6
138 next_option_offset = (UINT)sizeof(NX_IPV6_HEADER);
139 incoming_addr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr;
140 #endif /* FEATURE_NX_IPV6 */
141
142 /* Parse all options in the packet till we're done or an error is encountered. */
143 while (!drop_packet)
144 {
145
146 /* Add debug information. */
147 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
148
149 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_ICMPV6_ERROR_MESSAGE)
150 /* Set a local variable for convenience. */
151 nx_packet_option_offset = packet_ptr -> nx_packet_option_offset;
152 #endif /* defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_ICMPV6_ERROR_MESSAGE) */
153 switch (protocol)
154 {
155
156 #ifdef FEATURE_NX_IPV6
157 case NX_PROTOCOL_NEXT_HEADER_HOP_BY_HOP:
158
159 /* This should be the first header; if it is not, this is a malformed packet. */
160 if (packet_ptr -> nx_packet_option_state >= (UCHAR)HOP_BY_HOP_HEADER)
161 {
162
163 drop_packet = 1;
164
165 #ifndef NX_DISABLE_ICMPV6_ERROR_MESSAGE
166 NX_ICMPV6_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, 1, nx_packet_option_offset);
167 #endif /* NX_DISABLE_ICMPV6_ERROR_MESSAGE */
168 }
169 else
170 {
171
172 /* Start the option header handling. */
173 packet_ptr -> nx_packet_option_state = (UCHAR)HOP_BY_HOP_HEADER;
174
175 /* Dispatch packet to the Option handler. */
176 drop_packet = _nx_ipv6_process_hop_by_hop_option(ip_ptr, packet_ptr);
177 }
178
179 break;
180
181 case NX_PROTOCOL_NEXT_HEADER_DESTINATION:
182
183 /* Invalid header option if we have already processed 1 destination option. */
184 if (packet_ptr -> nx_packet_destination_header >= 1)
185 {
186
187 /* If we already have processed one destination option, we expect this
188 to be the second one. */
189 if ((packet_ptr -> nx_packet_option_state < (UCHAR)DESTINATION_HEADER_1) ||
190 (packet_ptr -> nx_packet_destination_header > 1))
191 {
192 drop_packet = 1;
193 }
194 else
195 {
196 packet_ptr -> nx_packet_option_state = (UCHAR)DESTINATION_HEADER_2;
197 }
198 }
199 else
200 {
201
202 /* This is the first time we encounter a destination header option. */
203 /* If we are before the routing header option, this must be the 1st one.
204 Otherwise, it must be the 2nd one. */
205
206 if (packet_ptr -> nx_packet_option_state < (UCHAR)ROUTING_HEADER)
207 {
208
209 packet_ptr -> nx_packet_option_state = (UCHAR)DESTINATION_HEADER_1;
210 }
211 else
212 {
213 packet_ptr -> nx_packet_option_state = (UCHAR)DESTINATION_HEADER_2;
214 }
215 }
216
217 packet_ptr -> nx_packet_destination_header++;
218
219 if (!drop_packet)
220 {
221 /* Proceed with hop by hop handling if there are no errors. */
222 drop_packet = _nx_ipv6_process_hop_by_hop_option(ip_ptr, packet_ptr);
223 }
224 #ifndef NX_DISABLE_ICMPV6_ERROR_MESSAGE
225 else
226 {
227
228 /* Return an error message to the sender of the packet. */
229 NX_ICMPV6_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, 1, nx_packet_option_offset);
230 }
231 #endif /* NX_DISABLE_ICMPV6_ERROR_MESSAGE */
232
233 break;
234
235 case NX_PROTOCOL_NEXT_HEADER_ROUTING:
236
237 if (packet_ptr -> nx_packet_option_state >= (UCHAR)ROUTING_HEADER)
238 {
239
240 #ifndef NX_DISABLE_ICMPV6_ERROR_MESSAGE
241 NX_ICMPV6_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, 1, nx_packet_option_offset);
242 #endif /* NX_DISABLE_ICMPV6_ERROR_MESSAGE */
243
244 drop_packet = 1;
245 }
246 else
247 {
248
249 packet_ptr -> nx_packet_option_state = (UCHAR)ROUTING_HEADER;
250
251 drop_packet = _nx_ipv6_process_routing_option(ip_ptr, packet_ptr);
252 }
253 break;
254
255 case NX_PROTOCOL_NEXT_HEADER_FRAGMENT:
256
257 #ifndef NX_DISABLE_FRAGMENTATION
258 if (packet_ptr -> nx_packet_option_state >= (UCHAR)FRAGMENT_HEADER)
259 {
260 #endif /* NX_DISABLE_FRAGMENTATION */
261
262 #ifndef NX_DISABLE_ICMPV6_ERROR_MESSAGE
263 NX_ICMPV6_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, 1, nx_packet_option_offset);
264 #endif /* NX_DISABLE_ICMPV6_ERROR_MESSAGE */
265
266 drop_packet = 1;
267 #ifndef NX_DISABLE_FRAGMENTATION
268 }
269 else
270 {
271
272 packet_ptr -> nx_packet_option_state = (UCHAR)FRAGMENT_HEADER;
273
274 #ifdef NX_ENABLE_LOW_WATERMARK
275 if (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available >=
276 packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark)
277 #endif
278 {
279 drop_packet = _nx_ipv6_process_fragment_option(ip_ptr, packet_ptr);
280 }
281 #ifdef NX_ENABLE_LOW_WATERMARK
282 else
283 {
284 drop_packet = NX_POOL_ERROR;
285 }
286 #endif
287
288 if (drop_packet != NX_CONTINUE)
289 {
290
291 /* Special case: do not further process the packet here.
292 Once all fragments are received, we will continue processing the headers. */
293 return(drop_packet);
294 }
295 else
296 {
297
298 /* Continue processing the packet. */
299 drop_packet = 0;
300 }
301 }
302 #endif /* NX_DISABLE_FRAGMENTATION */
303 break;
304
305 case NX_PROTOCOL_NO_NEXT_HEADER:
306
307 drop_packet = 1;
308 break;
309
310 #endif /* FEATURE_NX_IPV6 */
311
312 case NX_PROTOCOL_NEXT_HEADER_AUTHENTICATION:
313
314 #ifdef NX_IPSEC_ENABLE
315 if (ip_ptr -> nx_ip_ipsec_authentication_header_receive == NX_NULL)
316 {
317
318 /* If IPsec is not enabled by the application, drop the packet. */
319 return(1);
320 }
321 else
322 {
323
324 ret = ip_ptr -> nx_ip_ipsec_authentication_header_receive(ip_ptr, packet_ptr, &next_protocol, &packet_ptr);
325
326 if (ret == NX_SUCCESS)
327 {
328
329 /* Indicate that IPSec consumed the packet. */
330 return(0);
331 }
332
333 if (ret != NX_IPSEC_PKT_CONT)
334 {
335
336 return(1);
337 }
338
339 /* Continue processing the packet if status = NX_IPSEC_PKT_CONT */
340 }
341 #else /* NX_IPSEC_ENABLE */
342
343 /* Drop this packet if IPsec module is not present. */
344 drop_packet = 1;
345 #endif /* NX_IPSEC_ENABLE */
346
347 break;
348
349 case NX_PROTOCOL_NEXT_HEADER_ENCAP_SECURITY:
350
351 #ifdef NX_IPSEC_ENABLE
352 if (ip_ptr -> nx_ip_ipsec_encapsulating_security_payload_receive == NX_NULL)
353 {
354
355 /* If IPsec is not enabled by the application, drop the packet. */
356 return(1);
357 }
358 else
359 {
360
361 ret = ip_ptr -> nx_ip_ipsec_encapsulating_security_payload_receive(ip_ptr, packet_ptr, &next_protocol, &packet_ptr);
362
363 if (ret == NX_SUCCESS)
364 {
365
366 /* Indicate IPSec consumed the packet. */
367 return(0);
368 }
369
370 if (ret != NX_IPSEC_PKT_CONT)
371 {
372 return(1);
373 }
374
375 /* Continue processing the packet if status = NX_IPSEC_PKT_CONT */
376 }
377 break;
378
379 #else /* NX_IPSEC_ENABLE */
380 /* Drop this packet if IPsec module is not present. */
381 return(1);
382 #endif /* NX_IPSEC_ENABLE */
383
384 default:
385
386 /* Not part of the IP headers. */
387 #ifdef NX_IPSEC_ENABLE
388 /* Check ingress_sa for packet that is not ESP or AH. */
389 if (packet_ptr -> nx_packet_ipsec_sa_ptr == NX_NULL)
390 {
391
392 /* Get source and destination address. */
393 #ifdef FEATURE_NX_IPV6
394 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
395 {
396 ipv6_header = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_ip_header);
397
398 src_addr.nxd_ip_version = NX_IP_VERSION_V6;
399 dest_addr.nxd_ip_version = NX_IP_VERSION_V6;
400
401 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip,
402 src_addr.nxd_ip_address.v6);
403
404
405 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip,
406 dest_addr.nxd_ip_address.v6);
407 }
408 else
409 #endif /* FEATURE_NX_IPV6 */
410 {
411 #ifndef NX_DISABLE_IPV4
412 ipv4_header = (NX_IPV4_HEADER *)(packet_ptr -> nx_packet_ip_header);
413
414 src_addr.nxd_ip_version = NX_IP_VERSION_V4;
415 dest_addr.nxd_ip_version = NX_IP_VERSION_V4;
416
417 src_addr.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_source_ip;
418 dest_addr.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_destination_ip;
419 #endif /* NX_DISABLE_IPV4 */
420 }
421
422 if (_nx_ipsec_sa_ingress_lookup(ip_ptr, &src_addr, &dest_addr, 0, (UCHAR)protocol,
423 NX_NULL, packet_ptr -> nx_packet_prepend_ptr) != NX_IPSEC_TRAFFIC_BYPASS)
424 {
425 #ifdef FEATURE_NX_IPV6
426 /* Check whether it is a NA packet. */
427 if (protocol == NX_PROTOCOL_ICMPV6)
428 {
429
430 /* Bypass NA packet. */
431 icmp_header_ptr = (NX_ICMPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
432 if (icmp_header_ptr -> nx_icmpv6_header_type != NX_ICMPV6_NEIGHBOR_ADVERTISEMENT_TYPE)
433 {
434 return(NX_INVALID_PACKET);
435 }
436 }
437 else
438 {
439 #endif /* FEATURE_NX_IPV6 */
440 return(NX_INVALID_PACKET);
441 #ifdef FEATURE_NX_IPV6
442 }
443 #endif /* FEATURE_NX_IPV6 */
444 }
445 }
446 /* For IPsec tunnel mode, next protocol is checked here. */
447 else if (((NX_IPSEC_SA *)(packet_ptr -> nx_packet_ipsec_sa_ptr)) -> nx_ipsec_sa_mode == NX_IPSEC_TUNNEL_MODE)
448 {
449 if (_nx_ipsec_sa_ingress_selector_check(packet_ptr -> nx_packet_prepend_ptr,
450 (UCHAR)protocol,
451 ((NX_IPSEC_SA *)(packet_ptr -> nx_packet_ipsec_sa_ptr)) -> nx_ipsec_selector_ptr) == NX_IPSEC_TRAFFIC_DROP)
452 {
453 _nx_packet_release(packet_ptr); /* Consume the packet */
454 return(NX_INVALID_PACKET);
455 }
456 }
457 #endif /* NX_IPSEC_ENABLE */
458
459 #if defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER)
460 if ((ip_ptr -> nx_ip_raw_ip_processing) && (ip_ptr -> nx_ip_raw_packet_filter))
461 {
462
463 /* Let RAW packet filter handler filter all incoming packets. */
464 if ((ip_ptr -> nx_ip_raw_ip_processing)(ip_ptr, protocol << 16, packet_ptr) == NX_SUCCESS)
465 {
466 /* No need to free the packet as it is consumed by the raw process */
467 return(0);
468 }
469 }
470 #endif /* defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */
471
472 if (protocol == NX_PROTOCOL_TCP)
473 {
474 #ifdef FEATURE_NX_IPV6
475 if ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4) ||
476 ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) &&
477 (incoming_addr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)))
478 {
479 #endif /* FEATURE_NX_IPV6 */
480
481 /* Check that the host is enabled for TCP. */
482 if (ip_ptr -> nx_ip_tcp_packet_receive)
483 {
484
485 /* Dispatch the packet to the TCP packet handler. */
486 (ip_ptr -> nx_ip_tcp_packet_receive)(ip_ptr, packet_ptr);
487
488 /* No need to free the packet as it is consumed by TCP packet receive. */
489 return(0);
490 }
491 #ifdef FEATURE_NX_IPV6
492 }
493 #endif /* FEATURE_NX_IPV6 */
494
495 /* TCP is not enabled. Drop the packet. */
496 drop_packet = 1;
497 }
498
499 #ifdef FEATURE_NX_IPV6
500 else if ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) &&
501 (protocol == NX_PROTOCOL_ICMPV6))
502 {
503
504 /* Check that ICMPv6 is enabled for this IP instance. */
505 if (ip_ptr -> nx_ip_icmpv6_packet_process != NX_NULL)
506 {
507
508 /* Forward to the ICMPv6 packet handler. */
509 ip_ptr -> nx_ip_icmpv6_packet_process(ip_ptr, packet_ptr);
510
511 /* no need to free packet as it is consumed by ICMP packet receive. */
512 return(0);
513 }
514
515 /* ICMPv6 is not enabled. Drop the packet. */
516 drop_packet = 1;
517 }
518 #endif /* FEATURE_NX_IPV6 */
519
520 #ifndef NX_DISABLE_IPV4
521 else if ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4) &&
522 (protocol == NX_PROTOCOL_ICMP))
523 {
524
525 /* Check that ICMP is enabled for this IP instance. */
526 if (ip_ptr -> nx_ip_icmp_packet_receive != NX_NULL)
527 {
528
529 /* Yes, a ICMP packet is present, dispatch to the appropriate ICMP handler
530 if present. */
531 ip_ptr -> nx_ip_icmp_packet_receive(ip_ptr, packet_ptr);
532 return(0);
533 }
534
535 /* ICMP is not enabled. Drop the packet. */
536 drop_packet = 1;
537 }
538 else if ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4) &&
539 (protocol == NX_PROTOCOL_IGMP))
540 {
541 if (ip_ptr -> nx_ip_igmp_packet_receive != NX_NULL)
542 {
543
544 /* Yes, a IGMP packet is present, dispatch to the appropriate ICMP handler
545 if present. */
546 ip_ptr -> nx_ip_igmp_packet_receive(ip_ptr, packet_ptr);
547 return(0);
548 }
549
550 /* IGMP is not enabled. Drop the packet. */
551 drop_packet = 1;
552 }
553 #endif /* NX_DISABLE_IPV4 */
554 else if (protocol == NX_PROTOCOL_UDP)
555 {
556
557 #ifdef FEATURE_NX_IPV6
558 if ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4) ||
559 ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) &&
560 (incoming_addr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)))
561 {
562 #endif /* FEATURE_NX_IPV6 */
563
564 /* Check the host is enabled for UDP packet handling. */
565 if (ip_ptr -> nx_ip_udp_packet_receive)
566 {
567
568 /* Dispatch the packet to the UDP handler. */
569 (ip_ptr -> nx_ip_udp_packet_receive)(ip_ptr, packet_ptr);
570
571 /* No need to free the packet as it is consumed by UDP packet receive. */
572 return(0);
573 }
574 #ifdef FEATURE_NX_IPV6
575 }
576 #endif /* FEATURE_NX_IPV6 */
577
578 /* UDP is not enabled. Drop the packet. */
579 drop_packet = 1;
580 }
581 else
582 {
583 if (ip_ptr -> nx_ip_raw_ip_processing)
584 {
585 #if defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER)
586 if (ip_ptr -> nx_ip_raw_packet_filter == NX_NULL)
587 #endif /* defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */
588 {
589 if ((ip_ptr -> nx_ip_raw_ip_processing)(ip_ptr, protocol << 16, packet_ptr) == NX_SUCCESS)
590 {
591 /* No need to free the packet as it is consumed by the raw process */
592 return(0);
593 }
594 }
595 }
596
597 #if !defined(NX_DISABLE_IPV4) && !defined(NX_DISABLE_ICMPV4_ERROR_MESSAGE)
598 /* Unknown protocol, send ICMP Destination protocol unreachable. */
599 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
600 {
601 NX_ICMPV4_SEND_DEST_UNREACHABLE(ip_ptr, packet_ptr, NX_ICMP_PROTOCOL_UNREACH_CODE);
602 }
603 #endif /* !NX_DISABLE_IPV4 && !NX_DISABLE_ICMPV4_ERROR_MESSAGE */
604
605 #ifdef FEATURE_NX_IPV6
606 /* Unknown option. Send ICMP Parameter problem and discard the packet. */
607 /* RFC 2460, page 7 */
608 #ifndef NX_DISABLE_ICMPV6_ERROR_MESSAGE
609 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
610 {
611 NX_ICMPV6_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, 1, nx_packet_option_offset);
612 }
613 #endif /* NX_DISABLE_ICMPV6_ERROR_MESSAGE */
614 #endif /* FEATURE_NX_IPV6 */
615
616 #ifndef NX_DISABLE_IP_INFO
617
618 /* Increment the IP unknown protocol count. */
619 ip_ptr -> nx_ip_unknown_protocols_received++;
620
621 #endif /* NX_DISABLE_IP_INFO */
622
623
624 drop_packet = 1;
625 }
626 break;
627 }
628
629
630 /* If the previous header is processed without errors, move on to the next optional
631 header. */
632 if (!drop_packet)
633 {
634
635 #ifdef FEATURE_NX_IPV6
636 NX_IPV6_HEADER_OPTION *option;
637 ULONG option_hdr_len;
638 #endif /* FEATURE_NX_IPV6 */
639
640 #ifdef NX_IPSEC_ENABLE
641
642 if (protocol == NX_PROTOCOL_NEXT_HEADER_ENCAP_SECURITY ||
643 protocol == NX_PROTOCOL_NEXT_HEADER_AUTHENTICATION)
644 {
645
646 /* After ESP and AH processing, ESP and AH hdr are removed. */
647 protocol = next_protocol;
648 continue;
649 }
650 #endif /* NX_IPSEC_ENABLE */
651
652 #ifdef FEATURE_NX_IPV6
653 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
654 {
655
656 /* Find the option we just processed. */
657 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
658 option = (NX_IPV6_HEADER_OPTION *)packet_ptr -> nx_packet_prepend_ptr;
659
660 /* Check the protocol. */
661 if (protocol == NX_PROTOCOL_NEXT_HEADER_FRAGMENT)
662 {
663
664 /* Fixed length for fragment option, the field of option length is reserved. */
665 option_hdr_len = sizeof(NX_IPV6_HEADER_FRAGMENT_OPTION);
666 }
667 else
668 {
669
670 /* Compute the current option length. */
671 /* For other IPv6 optional headers, hdr_ext_len is expressed in 64-bit words. */
672 option_hdr_len = (ULONG)((option -> nx_ipv6_header_option_ext_length + 1) << 3);
673 }
674
675 /* Obtain the next option header type. */
676 protocol = option -> nx_ipv6_header_option_next_header;
677
678 if (((ALIGN_TYPE)(packet_ptr -> nx_packet_prepend_ptr) + option_hdr_len) <
679 (ALIGN_TYPE)(packet_ptr -> nx_packet_append_ptr))
680 {
681
682 /* Advance to the next header. */
683 packet_ptr -> nx_packet_prepend_ptr += option_hdr_len;
684 packet_ptr -> nx_packet_length -= option_hdr_len;
685 }
686 else
687 {
688
689 drop_packet = 1;
690 }
691
692 /*
693 Advance the nx_packet_option_offset as well.
694 Option Offset is used when constructing ICMPv6 parameter problem message.
695 */
696
697 packet_ptr -> nx_packet_option_offset = (USHORT)next_option_offset;
698
699 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
700 next_option_offset = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
701 }
702 #endif /* FEATURE_NX_IPV6 */
703 }
704 else
705 {
706 #ifndef NX_DISABLE_IP_INFO
707
708 /* Decrement the number of packets delivered. */
709 ip_ptr -> nx_ip_total_packets_delivered--;
710
711 /* Decrement the IP packet bytes received (not including the header). */
712 ip_ptr -> nx_ip_total_bytes_received -= packet_ptr -> nx_packet_length;
713
714 /* Increment the IP receive packets dropped count. */
715 ip_ptr -> nx_ip_receive_packets_dropped++;
716 #endif /* NX_DISABLE_IP_INFO */
717 }
718 }
719
720 return(drop_packet);
721 }
722
723