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