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