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 Control Message Protocol (ICMP)                            */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "nx_api.h"
29 #include "nx_ipv6.h"
30 #include "nx_icmpv6.h"
31 #include "nx_packet.h"
32 
33 #ifdef NX_IPSEC_ENABLE
34 #include "nx_ipsec.h"
35 #endif /* NX_IPSEC_ENABLE */
36 
37 
38 #ifdef FEATURE_NX_IPV6
39 
40 
41 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
42 
43 /**************************************************************************/
44 /*                                                                        */
45 /*  FUNCTION                                               RELEASE        */
46 /*                                                                        */
47 /*    _nx_icmpv6_process_packet_too_big                   PORTABLE C      */
48 /*                                                           6.3.0        */
49 /*  AUTHOR                                                                */
50 /*                                                                        */
51 /*    Yuxin Zhou, Microsoft Corporation                                   */
52 /*                                                                        */
53 /*  DESCRIPTION                                                           */
54 /*                                                                        */
55 /*    This function handles an ICMPv6 error message indicating the next   */
56 /*    hop or beyond has a smaller MTU that the packet payload.  It sets   */
57 /*    the IP task MTU to the next hop MTU in the option header.           */
58 /*                                                                        */
59 /*    This function is called from IP thread periodic process routine.    */
60 /*    It starts the minimum Path MTU Discovery process if the interface   */
61 /*    address after the IP instance is initialized and its MTU established*/
62 /*    by the Ethernet driver.                                             */
63 /*                                                                        */
64 /*  INPUT                                                                 */
65 /*                                                                        */
66 /*    ip_ptr                                Pointer to IP instance        */
67 /*    packet_ptr                            Pointer to Packet Too Big     */
68 /*                                            ICMPv6 packet received      */
69 /*                                                                        */
70 /*  OUTPUT                                                                */
71 /*                                                                        */
72 /*    NX_SUCCESS                            Successful completion         */
73 /*                                                                        */
74 /*  CALLS                                                                 */
75 /*                                                                        */
76 /*     _nx_icmpv6_dest_table_find         Find destination in table and   */
77 /*                                             update path MTU in table   */
78 /*    memset                              Set the memory                  */
79 /*                                                                        */
80 /*  CALLED BY                                                             */
81 /*                                                                        */
82 /*                                                                        */
83 /*  RELEASE HISTORY                                                       */
84 /*                                                                        */
85 /*    DATE              NAME                      DESCRIPTION             */
86 /*                                                                        */
87 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
88 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
89 /*                                            resulting in version 6.1    */
90 /*  10-31-2023     Bo Chen                  Modified comment(s), improved */
91 /*                                            packet length verification, */
92 /*                                            resulting in version 6.3.0  */
93 /*                                                                        */
94 /**************************************************************************/
_nx_icmpv6_process_packet_too_big(NX_IP * ip_ptr,NX_PACKET * packet_ptr)95 UINT _nx_icmpv6_process_packet_too_big(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
96 {
97 
98 UINT                       status = NX_INVALID_MTU_DATA;
99 NX_ICMPV6_OPTION_MTU      *icmpv6_mtu_option_ptr;
100 ULONG                      mtu;
101 NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
102 ULONG                     *original_destination_ip;
103 ULONG                      default_next_hop_address[4];
104 NX_IPV6_HEADER            *ip_header_ptr, *original_ip_header_ptr;
105 NX_INTERFACE              *if_ptr;
106 
107     /* Add debug information. */
108     NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
109 
110 #ifndef NX_DISABLE_RX_SIZE_CHECKING
111     if ((packet_ptr -> nx_packet_length < (sizeof(NX_ICMPV6_OPTION_MTU) + sizeof(NX_IPV6_HEADER)))
112 #ifndef NX_DISABLE_PACKET_CHAIN
113         || (packet_ptr -> nx_packet_next) /* Ignore chained packet.  */
114 #endif /* NX_DISABLE_PACKET_CHAIN */
115         )
116     {
117 #ifndef NX_DISABLE_ICMP_INFO
118 
119         /* Increment the ICMP invalid message count.  */
120         ip_ptr -> nx_ip_icmp_invalid_packets++;
121 #endif
122 
123         /* Invalid ICMP message, just release it.  */
124         _nx_packet_release(packet_ptr);
125         return(NX_NOT_SUCCESSFUL);
126     }
127 #endif /* NX_DISABLE_RX_SIZE_CHECKING */
128 
129     memset(&default_next_hop_address[0], 0, (4 * sizeof(ULONG)));
130 
131     if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
132 
133     /* Set a local pointer to the ICMPv6 Option data. */
134     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
135     icmpv6_mtu_option_ptr = (NX_ICMPV6_OPTION_MTU *)packet_ptr -> nx_packet_prepend_ptr;
136 
137     /* Parse the original sender data. */
138     /*lint -e{929} -e{826} -e{740} suppress cast of pointer to pointer, since it is necessary  */
139     original_ip_header_ptr = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_ICMPV6_OPTION_MTU));
140 
141     /* Extract the original sender from the IP header. */
142     packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV6_HEADER);
143 
144     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
145     ip_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
146 
147 
148     /* Yes this looks like a valid IP header for the original offending packet. */
149     original_destination_ip = original_ip_header_ptr -> nx_ip_header_destination_ip;
150     NX_IPV6_ADDRESS_CHANGE_ENDIAN(original_destination_ip);
151     COPY_IPV6_ADDRESS(ip_header_ptr -> nx_ip_header_source_ip, &default_next_hop_address[0]);
152 
153     /*  Handle endianness. */
154     NX_CHANGE_ULONG_ENDIAN(icmpv6_mtu_option_ptr -> nx_icmpv6_option_mtu_path_mtu);
155 
156     /* Create a local variable for convenience. */
157     mtu = icmpv6_mtu_option_ptr -> nx_icmpv6_option_mtu_path_mtu;
158 
159     /* MTU data is valid if it is non zero, and is no more than the driver MTU. */
160     if ((mtu > 0) && (mtu <= if_ptr -> nx_interface_ip_mtu_size))
161     {
162 
163         /* Add destination table. */
164         status = _nx_icmpv6_dest_table_add(ip_ptr, original_destination_ip,
165                                            &dest_entry_ptr, &default_next_hop_address[0], mtu, 0,
166                                            packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
167     }
168 
169     /* Release the packet. */
170     _nx_packet_release(packet_ptr);
171 
172     /* Return the completion code. */
173     return(status);
174 }
175 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
176 
177 
178 #endif /* FEATURE_NX_IPV6 */
179 
180