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 Protocol (IP) */
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_ip.h"
29 #include "nx_packet.h"
30 #include "nx_icmpv4.h"
31
32 #ifndef NX_DISABLE_IPV4
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_ipv4_option_process PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Yuxin Zhou, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function goes through IPv4 option fields. */
46 /* */
47 /* INPUT */
48 /* */
49 /* ip_ptr Pointer to IP control block */
50 /* packet_ptr Pointer to packet to send */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* _nx_ipv4_packet_receive Main IPv4 packet receive */
62 /* */
63 /* RELEASE HISTORY */
64 /* */
65 /* DATE NAME DESCRIPTION */
66 /* */
67 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
68 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
69 /* resulting in version 6.1 */
70 /* */
71 /**************************************************************************/
_nx_ipv4_option_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)72 UINT _nx_ipv4_option_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
73 {
74
75
76 NX_IPV4_HEADER *ip_header_ptr;
77 UCHAR *option_ptr;
78 ULONG ip_option_length;
79 #ifndef NX_DISABLE_ICMPV4_ERROR_MESSAGE
80 ULONG ip_normal_length = 20;
81 #endif /* NX_DISABLE_ICMPV4_ERROR_MESSAGE */
82 UINT index = 0;
83 UCHAR op_type;
84 UCHAR op_length;
85 UCHAR op_timestamp_offset;
86 UCHAR op_timestamp_overflow;
87 UCHAR op_timestamp_flags;
88 UINT op_timestamp_counter = 0;
89
90 /* Set the IPv4 header and IPv4 option pointer. */
91 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
92 ip_header_ptr = (NX_IPV4_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
93 option_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_IPV4_HEADER);
94
95 /* Calculate the IPv4 option length. */
96 ip_option_length = ((((ip_header_ptr -> nx_ip_header_word_0 & NX_IP_LENGTH_MASK) >> 24) - NX_IP_NORMAL_LENGTH) & 0xFF) * (ULONG)sizeof(ULONG);
97
98 /* Loop to process the IPv4 option. */
99 while (index < ip_option_length)
100 {
101
102 /* Get the option type. */
103 op_type = *option_ptr;
104
105 /* Process the option type. */
106 switch (op_type)
107 {
108
109 case NX_IP_OPTION_END:
110 {
111
112 /* End option. */
113 return(NX_TRUE);
114 }
115 case NX_IP_OPTION_NO_OPERATION:
116 {
117
118 /* No opeartion. */
119
120 /* Update the Option pointer and index. */
121 option_ptr++;
122 index++;
123 continue;
124 }
125 case NX_IP_OPTION_INTERNET_TIMESTAMP:
126 {
127
128 /* Timestamp option. RFC781. */
129
130 /* Update the counter; */
131 op_timestamp_counter++;
132
133 /* Check the counter. */
134 if (op_timestamp_counter > 1)
135 {
136 #ifndef NX_DISABLE_ICMPV4_ERROR_MESSAGE
137 /* Option length error, send a Parameter Problem Message . */
138 /*lint -e{835} -e{845} suppress operating on zero. */
139 NX_ICMPV4_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, NX_ICMP_ZERO_CODE, (ip_normal_length + index + 2));
140 #endif
141 /* Return NX_FALSE. */
142 return(NX_FALSE);
143 }
144
145 /* Get the option length. */
146 op_length = *(option_ptr + 1);
147
148 /* Get the option offset. */
149 op_timestamp_offset = *(option_ptr + 2);
150
151 /* Get the option overflow and flag. */
152 op_timestamp_overflow = (*(option_ptr + 3)) >> 4;
153 op_timestamp_flags = (*(option_ptr + 3)) & 0xF;
154
155 /* Only check the option errors. */
156
157 /* Check the option length error. */
158 if ((op_length < 8) || (op_length > 40) || ((op_length % 4) != 0))
159 {
160
161 #ifndef NX_DISABLE_ICMPV4_ERROR_MESSAGE
162 /* Option length error, send a Parameter Problem Message . */
163 /*lint -e{835} -e{845} suppress operating on zero. */
164 NX_ICMPV4_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, NX_ICMP_ZERO_CODE, (ip_normal_length + index + 2));
165 #endif
166
167 /* Return NX_FALSE. */
168 return(NX_FALSE);
169 }
170
171 /* Check the option offset error, offset must be greater than 5, and offset must be an odd number. */
172 if ((op_timestamp_offset < 5) || ((op_timestamp_offset % 2) == 0))
173 {
174
175 #ifndef NX_DISABLE_ICMPV4_ERROR_MESSAGE
176 /* Option offset error, send a Parameter Problem Message . */
177 /*lint -e{835} -e{845} suppress operating on zero. */
178 NX_ICMPV4_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, NX_ICMP_ZERO_CODE, (ip_normal_length + index + 3));
179 #endif
180
181 /* Return NX_FALSE. */
182 return(NX_FALSE);
183 }
184
185 /* Check the option overflow error. */
186 if (op_timestamp_overflow == 15)
187 {
188
189 #ifndef NX_DISABLE_ICMPV4_ERROR_MESSAGE
190 /* Option overflow error, send a Parameter Problem Message . */
191 /*lint -e{835} -e{845} suppress operating on zero. */
192 NX_ICMPV4_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, NX_ICMP_ZERO_CODE, (ip_normal_length + index + 4));
193 #endif
194
195 /* Return NX_FALSE. */
196 return(NX_FALSE);
197 }
198
199 /* Check the option flags error. */
200 if ((op_timestamp_flags != 0) && (op_timestamp_flags != 1) && (op_timestamp_flags != 3))
201 {
202
203 #ifndef NX_DISABLE_ICMPV4_ERROR_MESSAGE
204 /* Option flags error, send a Parameter Problem Message . */
205 /*lint -e{835} -e{845} suppress operating on zero. */
206 NX_ICMPV4_SEND_PARAMETER_PROBLEM(ip_ptr, packet_ptr, NX_ICMP_ZERO_CODE, (ip_normal_length + index + 4));
207 #endif
208
209 /* Return NX_FALSE. */
210 return(NX_FALSE);
211 }
212 break;
213 }
214 default:
215 break;
216 }
217
218 /* Get the option length. */
219 op_length = *(option_ptr + 1);
220
221 /* Check for invalid option length.
222 RFC 791: The option-length octet counts the option-type octet and the
223 option-length octet as well as the option-data octets. */
224 if ((op_length < 2) || ((index + op_length) > ip_option_length))
225 {
226 return(NX_FALSE);
227 }
228
229 /* Move to the next top level option. */
230 option_ptr += op_length;
231
232 /* Update the index. */
233 index += op_length;
234 }
235
236 /* Return NX_TRUE. */
237 return(NX_TRUE);
238 }
239 #endif /* !NX_DISABLE_IPV4 */
240
241