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 
26 /* Include necessary system files.  */
27 
28 #include "nx_api.h"
29 #include "nx_ipv6.h"
30 #include "nx_icmpv6.h"
31 
32 #ifdef FEATURE_NX_IPV6
33 
34 
35 /**************************************************************************/
36 /*                                                                        */
37 /*  FUNCTION                                               RELEASE        */
38 /*                                                                        */
39 /*    _nx_ipv6_process_hop_by_hop_option                  PORTABLE C      */
40 /*                                                           6.1.3        */
41 /*  AUTHOR                                                                */
42 /*                                                                        */
43 /*    Yuxin Zhou, Microsoft Corporation                                   */
44 /*                                                                        */
45 /*  DESCRIPTION                                                           */
46 /*                                                                        */
47 /*    This function processes the Hop by Hop and the Destination headers. */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    ip_ptr                                Pointer to IP control block   */
52 /*    packet_ptr                            Pointer to packet to process  */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    NX_SUCCESS                            Successful completion         */
57 /*    NX_OPTION_HEADER_ERROR                Error parsing packet options  */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    _nx_ipv6_option_error                Handle errors in IPv6 option   */
62 /*                                                                        */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    _nx_ipv6_dispatch_process            Process IPv6 optional header   */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
73 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
76 /*                                            buffer read overflow check, */
77 /*                                            resulting in version 6.1.3  */
78 /*                                                                        */
79 /**************************************************************************/
_nx_ipv6_process_hop_by_hop_option(NX_IP * ip_ptr,NX_PACKET * packet_ptr)80 UINT _nx_ipv6_process_hop_by_hop_option(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
81 {
82 
83 INT                        header_length;
84 UINT                       offset_base, offset;
85 UINT                       rv;
86 NX_IPV6_HOP_BY_HOP_OPTION *option;
87 
88 
89     /* Add debug information. */
90     NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
91 
92     /*  Make sure there's no OOB when reading Hdr Ext Len from the packet buffer. */
93     if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < 2)
94     {
95 
96         /* return an error code. */
97         return(NX_OPTION_HEADER_ERROR);
98     }
99 
100     /* Read the Hdr Ext Len field. */
101     header_length = *(packet_ptr -> nx_packet_prepend_ptr + 1);
102 
103     /* Calculate the the true header length: (n + 1) * 8 */
104     header_length = (header_length + 1) << 3;
105 
106     /* The 1st option starts from the 3rd byte. */
107     offset = 2;
108 
109     /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
110     /*lint -e{737} suppress loss of sign, since nx_packet_append_ptr is assumed to be larger than nx_packet_ip_header. */
111     offset_base = (UINT)((ULONG)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header) - (ULONG)sizeof(NX_IPV6_HEADER));
112     header_length = header_length - (INT)offset;
113 
114     /* Sanity check; does the header length data go past the end of the end of the packet buffer? */
115     /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
116     if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) <
117         ((UINT)header_length + offset))
118     {
119 
120         /* Yes, handle the error as indicated by the option type 2 msb's. */
121         /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
122         option = (NX_IPV6_HOP_BY_HOP_OPTION *)(packet_ptr -> nx_packet_prepend_ptr + offset);
123 
124         _nx_ipv6_option_error(ip_ptr, packet_ptr, option -> nx_ipv6_hop_by_hop_option_type, offset_base + offset);
125         return(NX_OPTION_HEADER_ERROR);
126     }
127 
128     while (header_length > 0)
129     {
130 
131         /* Get a pointer to the options. */
132         /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
133         option = (NX_IPV6_HOP_BY_HOP_OPTION *)(packet_ptr -> nx_packet_prepend_ptr + offset);
134 
135         switch (option -> nx_ipv6_hop_by_hop_option_type)
136         {
137 
138         case 0:
139 
140             /* Pad1 option.  This option indicates the size of the padding is one.
141                So we skip one byte. */
142             offset++;
143             header_length--;
144             break;
145 
146         case 1:
147 
148             /* PadN option. Skip N+2 bytes. */
149             offset += ((UINT)(option -> nx_ipv6_hop_by_hop_length) + 2);
150             header_length -= ((INT)(option -> nx_ipv6_hop_by_hop_length) + 2);
151             break;
152 
153 #ifdef NX_ENABLE_THREAD
154         case 109:
155 
156             /* RFC 7731.  */
157 
158             /* Skip N+2 bytes.  */
159             offset += ((UINT)(option -> nx_ipv6_hop_by_hop_length) + 2);
160             header_length -= ((INT)(option -> nx_ipv6_hop_by_hop_length) + 2);
161             break;
162 #endif /* NX_ENABLE_THREAD  */
163 
164         default:
165 
166             /* Unknown option.  */
167             rv = _nx_ipv6_option_error(ip_ptr, packet_ptr, option -> nx_ipv6_hop_by_hop_option_type, offset_base + offset);
168 
169             /* If no errors, just skip this option and move onto the next option.*/
170             if (rv == NX_SUCCESS)
171             {
172 
173                 /* Skip this option and continue processing the rest of the header. */
174                 offset += ((UINT)(option -> nx_ipv6_hop_by_hop_length) + 2);
175                 header_length -= ((INT)(option -> nx_ipv6_hop_by_hop_length) + 2);
176                 break;
177             }
178             else
179             {
180 
181                 /* Return value indicates an error status: we need to drop the entire packet. */
182                 return(rv); /* Drop this packet. */
183             }
184         }
185     }
186 
187     /* Successful processing of option header. */
188     return(NX_SUCCESS);
189 }
190 
191 #endif /*  FEATURE_NX_IPV6 */
192 
193