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