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