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