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 Protocol (IP) */
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_ip.h"
30 #include "nx_packet.h"
31 #include "nx_icmpv4.h"
32
33 #include "nx_ipv6.h"
34 #include "nx_icmpv6.h"
35
36 #ifndef NX_DISABLE_FRAGMENTATION
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _nx_ip_fragment_timeout_cleanup PORTABLE C */
42 /* 6.1 */
43 /* AUTHOR */
44 /* */
45 /* Yuxin Zhou, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This internal function cleans up outstanding IP fragments. */
50 /* */
51 /* INPUT */
52 /* */
53 /* ip_ptr Pointer to IP instance */
54 /* fragment The head of an IP fragment */
55 /* that needs to be cleaned. */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* None */
60 /* */
61 /* CALLS */
62 /* */
63 /* _nx_packet_release Release packet */
64 /* IPv6_Address_Type Find IPv6 address type. */
65 /* */
66 /* CALLED BY */
67 /* */
68 /* _nx_ip_fragment_timeout_check */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
75 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
76 /* resulting in version 6.1 */
77 /* */
78 /**************************************************************************/
_nx_ip_fragment_cleanup(NX_IP * ip_ptr,NX_PACKET * fragment)79 static VOID _nx_ip_fragment_cleanup(NX_IP *ip_ptr, NX_PACKET *fragment)
80 {
81
82 NX_PACKET *next_fragment;
83 #if !defined(NX_DISABLE_IPV4) && !defined(NX_DISABLE_ICMPV4_ERROR_MESSAGE)
84 NX_IPV4_HEADER *ipv4_header;
85 #endif /* !NX_DISABLE_IPV4 && !NX_DISABLE_ICMPV4_ERROR_MESSAGE */
86 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_ICMPV6_ERROR_MESSAGE)
87 NX_IPV6_HEADER_FRAGMENT_OPTION *fragment_option;
88 NX_IPV6_HEADER *ipv6_header;
89 #endif /* FEATURE_NX_IPV6 && !NX_DISABLE_ICMPV6_ERROR_MESSAGE */
90
91 #ifndef NX_DISABLE_IP_INFO
92 /* Increment the re-assembly failures count. */
93 ip_ptr -> nx_ip_reassembly_failures++;
94 #endif
95
96 #if !defined(NX_DISABLE_IPV4) && !defined(NX_DISABLE_ICMPV4_ERROR_MESSAGE)
97 /* If ICMPv4 is enabled, send Destination unreachable. */
98 if (fragment -> nx_packet_ip_version == NX_IP_VERSION_V4)
99 {
100
101 /* Setup header pointer for this packet. */
102 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
103 ipv4_header = (NX_IPV4_HEADER *)fragment -> nx_packet_ip_header;
104
105 /* Time Exceeded Message, RFC 792, P2. */
106 /* Check if the fragment zero is available. */
107 if ((ipv4_header -> nx_ip_header_word_1 & NX_IP_OFFSET_MASK) == 0)
108 {
109
110 /* Send a time exceeded message if fragmented datagram cannot complete the reassembly. */
111 NX_ICMPV4_SEND_TIME_EXCEED(ip_ptr, fragment, NX_ICMP_FRT_EXCEEDED_CODE);
112 }
113 }
114 #endif /* !NX_DISABLE_IPV4 && !NX_DISABLE_ICMPV4_ERROR_MESSAGE */
115
116 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_ICMPV6_ERROR_MESSAGE)
117 /* If the packet is IPv6 type, we need to send out ICMP error message. */
118 if (fragment -> nx_packet_ip_version == NX_IP_VERSION_V6)
119 {
120
121 /* Send out ICMP Time Exceeded message, if the first fragment has been received
122 as per RFC2460 4.5 */
123 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
124 fragment_option = (NX_IPV6_HEADER_FRAGMENT_OPTION *)fragment -> nx_packet_prepend_ptr;
125
126 if ((fragment_option -> nx_ipv6_header_fragment_option_offset_flag & 0xFFF8) == 0)
127 {
128
129 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
130 ipv6_header = (NX_IPV6_HEADER *)fragment -> nx_packet_ip_header;
131
132 /* First fragment has been received. Send ICMP error message, if the destination
133 is not multicast. */
134
135 if (!(IPv6_Address_Type(ipv6_header -> nx_ip_header_destination_ip) & IPV6_ADDRESS_MULTICAST))
136 {
137
138 /* Cover offset flag field. */
139 NX_CHANGE_USHORT_ENDIAN(fragment_option -> nx_ipv6_header_fragment_option_offset_flag);
140 NX_ICMPV6_SEND_TIME_EXCEED(ip_ptr, fragment, 1);
141 }
142 }
143 }
144 #endif /* FEATURE_NX_IPV6 && !NX_DISABLE_ICMPV6_ERROR_MESSAGE */
145
146 /* Walk the chain of fragments for this fragment re-assembly. */
147 do
148 {
149
150 #ifndef NX_DISABLE_IP_INFO
151
152 /* Increment the IP receive packets dropped count. */
153 ip_ptr -> nx_ip_receive_packets_dropped++;
154 #endif
155
156 /* Pickup the next fragment. */
157 next_fragment = fragment -> nx_packet_union_next.nx_packet_fragment_next;
158
159 /* Reset tcp_queue_next before releasing. */
160 /*lint -e{923} suppress cast of ULONG to pointer. */
161 fragment -> nx_packet_union_next.nx_packet_tcp_queue_next = (NX_PACKET *)NX_PACKET_ALLOCATED;
162
163 /* Release this fragment. */
164 _nx_packet_release(fragment);
165
166 /* Reassign the fragment pointer. */
167 fragment = next_fragment;
168 } while (fragment);
169 }
170
171
172
173 /**************************************************************************/
174 /* */
175 /* FUNCTION RELEASE */
176 /* */
177 /* _nx_ip_fragment_timeout_check PORTABLE C */
178 /* 6.1 */
179 /* AUTHOR */
180 /* */
181 /* Yuxin Zhou, Microsoft Corporation */
182 /* */
183 /* DESCRIPTION */
184 /* */
185 /* This function checks for timeout conditions on the first fragment */
186 /* in the IP re-assembly list. If the head pointer is the same */
187 /* between execution of this routine, the head fragment is deleted and */
188 /* its packets are released. */
189 /* */
190 /* INPUT */
191 /* */
192 /* ip_ptr Pointer to IP instance */
193 /* */
194 /* OUTPUT */
195 /* */
196 /* None */
197 /* */
198 /* CALLS */
199 /* */
200 /* _nx_packet_release Release packet */
201 /* */
202 /* CALLED BY */
203 /* */
204 /* Application */
205 /* */
206 /* RELEASE HISTORY */
207 /* */
208 /* DATE NAME DESCRIPTION */
209 /* */
210 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
211 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
212 /* resulting in version 6.1 */
213 /* */
214 /**************************************************************************/
_nx_ip_fragment_timeout_check(NX_IP * ip_ptr)215 VOID _nx_ip_fragment_timeout_check(NX_IP *ip_ptr)
216 {
217
218 NX_PACKET *fragment;
219 NX_PACKET *next_fragment;
220 NX_PACKET *previous_fragment = NX_NULL;
221
222
223 /* Set a pointer to the head packet of the fragmented packet queue. */
224 fragment = ip_ptr -> nx_ip_fragment_assembly_head;
225
226
227 /* Loop through all the fragmented packets in the queue. */
228 while (fragment)
229 {
230
231 /* Check if the timeout has expired. */
232 if (fragment -> nx_packet_reassembly_time == 0)
233 {
234
235 /* Timeout occured. */
236 next_fragment = fragment -> nx_packet_queue_next;
237
238 /* Remove the packet from the queue and connect the linked list around it. */
239 if (previous_fragment == NX_NULL)
240 {
241 ip_ptr -> nx_ip_fragment_assembly_head = next_fragment;
242 }
243 else
244 {
245 previous_fragment -> nx_packet_queue_next = next_fragment;
246 }
247
248 /* Send out an error message, release the packet fragments in this chain. */
249 _nx_ip_fragment_cleanup(ip_ptr, fragment);
250
251 /* If this was the last one in the queue, reset the tail to
252 the previous fragment. */
253 if (fragment == ip_ptr -> nx_ip_fragment_assembly_tail)
254 {
255 ip_ptr -> nx_ip_fragment_assembly_tail = previous_fragment;
256 }
257
258 /* Get the next fragmented packet awaiting assembly. */
259 fragment = next_fragment;
260 }
261 else
262 {
263
264 /* Decrement the time remaining to assemble the whole packet. */
265 fragment -> nx_packet_reassembly_time--;
266
267 /* Get the next packet fragment. */
268 previous_fragment = fragment;
269 fragment = fragment -> nx_packet_queue_next;
270 }
271 }
272 }
273 #endif /* NX_DISABLE_FRAGMENTATION */
274
275