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.1          */
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 /*                                                                        */
91 /**************************************************************************/
_nx_icmpv6_process_packet_too_big(NX_IP * ip_ptr,NX_PACKET * packet_ptr)92 UINT _nx_icmpv6_process_packet_too_big(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
93 {
94 
95 UINT                       status = NX_INVALID_MTU_DATA;
96 NX_ICMPV6_OPTION_MTU      *icmpv6_mtu_option_ptr;
97 ULONG                      mtu;
98 NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
99 ULONG                     *original_destination_ip;
100 ULONG                      default_next_hop_address[4];
101 NX_IPV6_HEADER            *ip_header_ptr, *original_ip_header_ptr;
102 NX_INTERFACE              *if_ptr;
103 
104     /* Add debug information. */
105     NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
106 
107 #ifndef NX_DISABLE_RX_SIZE_CHECKING
108     if (packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_OPTION_MTU))
109     {
110 #ifndef NX_DISABLE_ICMP_INFO
111 
112         /* Increment the ICMP invalid message count.  */
113         ip_ptr -> nx_ip_icmp_invalid_packets++;
114 #endif
115 
116         /* Invalid ICMP message, just release it.  */
117         _nx_packet_release(packet_ptr);
118         return(NX_NOT_SUCCESSFUL);
119     }
120 #endif /* NX_DISABLE_RX_SIZE_CHECKING */
121 
122     memset(&default_next_hop_address[0], 0, (4 * sizeof(ULONG)));
123 
124     if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
125 
126     /* Set a local pointer to the ICMPv6 Option data. */
127     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
128     icmpv6_mtu_option_ptr = (NX_ICMPV6_OPTION_MTU *)packet_ptr -> nx_packet_prepend_ptr;
129 
130     /* Parse the original sender data. */
131     /*lint -e{929} -e{826} -e{740} suppress cast of pointer to pointer, since it is necessary  */
132     original_ip_header_ptr = (NX_IPV6_HEADER *)(&(icmpv6_mtu_option_ptr ->  nx_icmpv6_option_mtu_message));
133 
134     /* Extract the original sender from the IP header. */
135     packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV6_HEADER);
136 
137     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
138     ip_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
139 
140 
141     /* Yes this looks like a valid IP header for the original offending packet. */
142     original_destination_ip = original_ip_header_ptr -> nx_ip_header_destination_ip;
143     NX_IPV6_ADDRESS_CHANGE_ENDIAN(original_destination_ip);
144     COPY_IPV6_ADDRESS(ip_header_ptr -> nx_ip_header_source_ip, &default_next_hop_address[0]);
145 
146     /*  Handle endianness. */
147     NX_CHANGE_ULONG_ENDIAN(icmpv6_mtu_option_ptr -> nx_icmpv6_option_mtu_path_mtu);
148 
149     /* Create a local variable for convenience. */
150     mtu = icmpv6_mtu_option_ptr -> nx_icmpv6_option_mtu_path_mtu;
151 
152     /* MTU data is valid if it is non zero, and is no more than the driver MTU. */
153     if ((mtu > 0) && (mtu <= if_ptr -> nx_interface_ip_mtu_size))
154     {
155 
156         /* Add destination table. */
157         status = _nx_icmpv6_dest_table_add(ip_ptr, original_destination_ip,
158                                            &dest_entry_ptr, &default_next_hop_address[0], mtu, 0,
159                                            packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
160     }
161 
162     /* Release the packet. */
163     _nx_packet_release(packet_ptr);
164 
165     /* Return the completion code. */
166     return(status);
167 }
168 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
169 
170 
171 #endif /* FEATURE_NX_IPV6 */
172 
173