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 /** User Datagram Protocol (UDP) */
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_udp.h"
30 #include "nx_packet.h"
31 #include "nx_ipv6.h"
32
33
34 /* Bring in externs for caller checking code. */
35
36 NX_CALLER_CHECKING_EXTERNS
37
38
39 /**************************************************************************/
40 /* */
41 /* FUNCTION RELEASE */
42 /* */
43 /* _nxde_udp_socket_send PORTABLE C */
44 /* 6.1 */
45 /* AUTHOR */
46 /* */
47 /* Yuxin Zhou, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function checks for errors in the UDP socket send */
52 /* function call. */
53 /* */
54 /* INPUT */
55 /* */
56 /* socket_ptr Pointer to UDP socket */
57 /* packet_ptr Pointer to UDP packet */
58 /* ip_address IP address */
59 /* port 16-bit UDP port number */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* status Completion status */
64 /* NX_PTR_ERROR Invalid pointer input or */
65 /* invalid packet input */
66 /* NX_NOT_ENABLED UDP not enabled on IP instance*/
67 /* NX_IP_ADDRESS_ERROR Invalid IP address input */
68 /* NX_INVALID_PORT Invalid UDP destination port */
69 /* NX_UNDERFLOW Check for invalid packet */
70 /* prepend pointer */
71 /* NX_OVERFLOW Check for invalid packet */
72 /* prepend pointer */
73 /* */
74 /* CALLS */
75 /* */
76 /* _nxd_udp_socket_send Actual UDP socket send */
77 /* function */
78 /* */
79 /* CALLED BY */
80 /* */
81 /* Application Code */
82 /* */
83 /* RELEASE HISTORY */
84 /* */
85 /* DATE NAME DESCRIPTION */
86 /* */
87 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
88 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
89 /* resulting in version 6.1 */
90 /* */
91 /**************************************************************************/
_nxde_udp_socket_send(NX_UDP_SOCKET * socket_ptr,NX_PACKET ** packet_ptr_ptr,NXD_ADDRESS * ip_address,UINT port)92 UINT _nxde_udp_socket_send(NX_UDP_SOCKET *socket_ptr, NX_PACKET **packet_ptr_ptr, NXD_ADDRESS *ip_address, UINT port)
93 {
94
95 NX_PACKET *packet_ptr;
96 UINT status;
97 UINT ip_header_size = 0;
98
99
100 /* Setup packet pointer. */
101 packet_ptr = *packet_ptr_ptr;
102
103 /* Check for invalid input pointers. */
104 if ((socket_ptr == NX_NULL) || (socket_ptr -> nx_udp_socket_id != NX_UDP_ID) || (ip_address == NX_NULL))
105 {
106 return(NX_PTR_ERROR);
107 }
108
109 /* Check for invalid packet pointers and packets not marked for allocation. */
110 /* Cast the ULONG into a packet pointer. Since this is exactly what we wish to do, disable the lint warning with the following comment: */
111 /*lint -e{923} suppress cast of ULONG to pointer. */
112 if ((packet_ptr == NX_NULL) ||
113 (packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next != ((NX_PACKET *)NX_PACKET_ALLOCATED)))
114 {
115
116 return(NX_PTR_ERROR);
117 }
118
119 /* Check if UDP is enabled. */
120 if (!(socket_ptr -> nx_udp_socket_ip_ptr) -> nx_ip_udp_packet_receive)
121 {
122 return(NX_NOT_ENABLED);
123 }
124
125
126 if ((ip_address -> nxd_ip_version != NX_IP_VERSION_V4) &&
127 (ip_address -> nxd_ip_version != NX_IP_VERSION_V6))
128 {
129 return(NX_IP_ADDRESS_ERROR);
130 }
131
132 #ifndef NX_DISABLE_IPV4
133 if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
134 {
135 if (ip_address -> nxd_ip_address.v4 == 0)
136 {
137 return(NX_IP_ADDRESS_ERROR);
138 }
139
140 ip_header_size = (UINT)sizeof(NX_IPV4_HEADER);
141 }
142 #endif /* !NX_DISABLE_IPV4 */
143
144 #ifdef FEATURE_NX_IPV6
145 if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
146 {
147 /* Check for invalid IP address. */
148 if (CHECK_UNSPECIFIED_ADDRESS(&ip_address -> nxd_ip_address.v6[0]))
149 {
150 return(NX_IP_ADDRESS_ERROR);
151 }
152
153 ip_header_size = (UINT)sizeof(NX_IPV6_HEADER);
154 }
155 #endif /* FEATURE_NX_IPV6 */
156
157 /* Check for an invalid port. */
158 if (((ULONG)port) > (ULONG)NX_MAX_PORT)
159 {
160 return(NX_INVALID_PORT);
161 }
162
163 /* Check for an invalid packet prepend pointer. */
164 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
165 if ((INT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start) < (INT)(ip_header_size + sizeof(NX_UDP_HEADER)))
166 {
167
168 #ifndef NX_DISABLE_UDP_INFO
169 /* Increment the total UDP invalid packet count. */
170 (socket_ptr -> nx_udp_socket_ip_ptr) -> nx_ip_udp_invalid_packets++;
171
172 /* Increment the total UDP invalid packet count for this socket. */
173 socket_ptr -> nx_udp_socket_invalid_packets++;
174 #endif
175
176 /* Return error code. */
177 return(NX_UNDERFLOW);
178 }
179
180 /* Check for an invalid packet append pointer. */
181 /*lint -e{946} suppress pointer subtraction, since it is necessary. */
182 if (packet_ptr -> nx_packet_append_ptr > packet_ptr -> nx_packet_data_end)
183 {
184
185 #ifndef NX_DISABLE_UDP_INFO
186 /* Increment the total UDP invalid packet count. */
187 (socket_ptr -> nx_udp_socket_ip_ptr) -> nx_ip_udp_invalid_packets++;
188
189 /* Increment the total UDP invalid packet count for this socket. */
190 socket_ptr -> nx_udp_socket_invalid_packets++;
191 #endif
192
193 /* Return error code. */
194 return(NX_OVERFLOW);
195 }
196
197 /* Check for appropriate caller. */
198 NX_THREADS_ONLY_CALLER_CHECKING
199
200 /* Call actual UDP socket send function. */
201 status = _nxd_udp_socket_send(socket_ptr, packet_ptr, ip_address, port);
202
203 /* Determine if the packet send was successful. */
204 if (status == NX_SUCCESS)
205 {
206
207 /* Yes, now clear the application's packet pointer so it can't be accidentally
208 used again by the application. This is only done when error checking is
209 enabled. */
210 *packet_ptr_ptr = NX_NULL;
211 }
212
213 /* Return completion status. */
214 return(status);
215 }
216
217