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_packet.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _nx_packet_data_extract_offset                      PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Yuxin Zhou, Microsoft Corporation                                   */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function copies data from a NetX packet (or packet chain) into */
44 /*    the supplied user buffer.   If an empty packet (no data) is         */
45 /*    received, zero bytes are copied, and the function returns without   */
46 /*    errors.                                                             */
47 /*                                                                        */
48 /*    Note that this function extracts data from a packet into user       */
49 /*    supplied buffer.  It does not modify packet internal state          */
50 /*    information.  The data being extracted is still available in the    */
51 /*    original packet for consumption again.                              */
52 /*                                                                        */
53 /*  INPUT                                                                 */
54 /*                                                                        */
55 /*    packet_ptr                        Pointer to the source packet      */
56 /*    offset                            Offset from start of data         */
57 /*    buffer_start                      Pointer to destination data area  */
58 /*    buffer_length                     Size in bytes                     */
59 /*    bytes_copied                      Number of bytes copied            */
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    status                            Completion status                 */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    None                                                                */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    Application Code                                                    */
72 /*                                                                        */
73 /*  RELEASE HISTORY                                                       */
74 /*                                                                        */
75 /*    DATE              NAME                      DESCRIPTION             */
76 /*                                                                        */
77 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
78 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
79 /*                                            verified memcpy use cases,  */
80 /*                                            resulting in version 6.1    */
81 /*                                                                        */
82 /**************************************************************************/
_nx_packet_data_extract_offset(NX_PACKET * packet_ptr,ULONG offset,VOID * buffer_start,ULONG buffer_length,ULONG * bytes_copied)83 UINT  _nx_packet_data_extract_offset(NX_PACKET *packet_ptr, ULONG offset, VOID *buffer_start, ULONG buffer_length, ULONG *bytes_copied)
84 {
85 
86 ULONG      remaining_bytes;
87 UCHAR     *source_ptr;
88 UCHAR     *destination_ptr;
89 ULONG      offset_bytes;
90 #ifndef NX_DISABLE_PACKET_CHAIN
91 ULONG      packet_fragment_length;
92 #endif /* NX_DISABLE_PACKET_CHAIN */
93 ULONG      bytes_to_copy;
94 NX_PACKET *working_packet_ptr;
95 
96 
97     working_packet_ptr =  packet_ptr;
98 
99     /* Check for an invalid offset or packet length.  */
100     if (offset >= working_packet_ptr -> nx_packet_length)
101     {
102 
103         /* Note: A zero offset with a packet of zero length is ok. */
104         if (offset == 0)
105         {
106 
107             *bytes_copied = 0;
108             return(NX_SUCCESS);
109         }
110 
111         /* Otherwise, this is an invalid offset or packet length. */
112         return(NX_PACKET_OFFSET_ERROR);
113     }
114 
115 
116     /* Initialize the source pointer to NULL.  */
117     source_ptr =  NX_NULL;
118 
119     /* Traverse packet chain to offset.  */
120     offset_bytes =  offset;
121 #ifndef NX_DISABLE_PACKET_CHAIN
122     while (working_packet_ptr)
123     {
124 
125         /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
126         packet_fragment_length =  (ULONG)((working_packet_ptr -> nx_packet_append_ptr - working_packet_ptr -> nx_packet_prepend_ptr));
127 
128         /* Determine if we are at the offset location fragment in the packet chain  */
129         if (packet_fragment_length > offset_bytes)
130         {
131 
132             /* Setup loop to copy from this packet.  */
133             source_ptr =  working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
134 
135             /* Yes, get out of this  loop.  */
136             break;
137         }
138 
139 
140         /* Decrement the remaining offset bytes*/
141         offset_bytes = offset_bytes - packet_fragment_length;
142 
143         /* Move to next packet.  */
144         working_packet_ptr =  working_packet_ptr -> nx_packet_next;
145     }
146 #else /* NX_DISABLE_PACKET_CHAIN */
147     /* Setup loop to copy from this packet.  */
148     source_ptr =  working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
149 
150 #endif /* NX_DISABLE_PACKET_CHAIN */
151 
152     /* Check for a valid source pointer.  */
153     if (source_ptr == NX_NULL)
154     {
155         return(NX_PACKET_OFFSET_ERROR);
156     }
157 
158     /* Setup the destination pointer.  */
159     destination_ptr =  buffer_start;
160     bytes_to_copy =   (packet_ptr -> nx_packet_length - offset);
161 
162     /* Pickup the amount of bytes to copy.  */
163     if (bytes_to_copy < buffer_length)
164     {
165         *bytes_copied =  bytes_to_copy;     /* the amount of bytes returned to the caller */
166         remaining_bytes =  bytes_to_copy;   /* for use in the copy loop */
167     }
168     else
169     {
170         *bytes_copied =  buffer_length;
171         remaining_bytes =  buffer_length;
172     }
173 
174 #ifndef NX_DISABLE_PACKET_CHAIN
175     /* Loop to copy bytes from packet(s).  */
176     while (working_packet_ptr && remaining_bytes)
177     {
178 #endif /* NX_DISABLE_PACKET_CHAIN */
179 
180         /* Calculate bytes to copy.  */
181         /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
182         bytes_to_copy = (ULONG)(working_packet_ptr -> nx_packet_append_ptr - source_ptr);
183         if (remaining_bytes < bytes_to_copy)
184         {
185             bytes_to_copy = remaining_bytes;
186         }
187 
188         /* Copy data from this packet.  */
189         memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */
190 
191         /* Update the pointers. */
192         destination_ptr += bytes_to_copy;
193         remaining_bytes -= bytes_to_copy;
194 
195 #ifndef NX_DISABLE_PACKET_CHAIN
196         /* Move to next packet.  */
197         working_packet_ptr =  working_packet_ptr -> nx_packet_next;
198 
199         /* Check for a next packet.  */
200         if (working_packet_ptr)
201         {
202 
203             /* Setup new source pointer.  */
204             source_ptr = working_packet_ptr -> nx_packet_prepend_ptr;
205         }
206     }
207 #endif /* NX_DISABLE_PACKET_CHAIN */
208 
209     /* If trace is enabled, insert this event into the trace buffer.  */
210     NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_DATA_EXTRACT_OFFSET, packet_ptr, buffer_length, *bytes_copied, 0, NX_TRACE_PACKET_EVENTS, 0, 0);
211 
212     /* Return successful completion.  */
213     return(NX_SUCCESS);
214 }
215 
216