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