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