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 /** Transmission Control Protocol (TCP) */
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_tcp.h"
30
31
32 /* Bring in externs for caller checking code. */
33
34 NX_CALLER_CHECKING_EXTERNS
35
36
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _nxe_tcp_socket_create PORTABLE C */
42 /* 6.1 */
43 /* AUTHOR */
44 /* */
45 /* Yuxin Zhou, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function checks for errors in the TCP socket create */
50 /* function call. */
51 /* */
52 /* INPUT */
53 /* */
54 /* ip_ptr IP instance pointer */
55 /* socket_ptr Pointer to new TCP socket */
56 /* name Name of new TCP socket */
57 /* type_of_service Type of service for this TCP */
58 /* socket */
59 /* fragment Flag to enable IP fragmenting */
60 /* time_to_live Time to live value for socket */
61 /* window_size Size of socket's receive */
62 /* window */
63 /* tcp_urgent_data_callback Routine to call when urgent */
64 /* data is received */
65 /* tcp_disconnect_callback Routine to call when a */
66 /* disconnect occurs */
67 /* tcp_socket_size Size of TCP socket */
68 /* */
69 /* OUTPUT */
70 /* */
71 /* status Completion status */
72 /* */
73 /* CALLS */
74 /* */
75 /* _nx_tcp_socket_create Actual TCP socket create */
76 /* function */
77 /* tx_mutex_get Get protection mutex */
78 /* tx_mutex_put Put protection mutex */
79 /* */
80 /* CALLED BY */
81 /* */
82 /* Application Code */
83 /* */
84 /* RELEASE HISTORY */
85 /* */
86 /* DATE NAME DESCRIPTION */
87 /* */
88 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
89 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
90 /* resulting in version 6.1 */
91 /* */
92 /**************************************************************************/
_nxe_tcp_socket_create(NX_IP * ip_ptr,NX_TCP_SOCKET * socket_ptr,CHAR * name,ULONG type_of_service,ULONG fragment,UINT time_to_live,ULONG window_size,VOID (* tcp_urgent_data_callback)(NX_TCP_SOCKET * socket_ptr),VOID (* tcp_disconnect_callback)(NX_TCP_SOCKET * socket_ptr),UINT tcp_socket_size)93 UINT _nxe_tcp_socket_create(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, CHAR *name,
94 ULONG type_of_service, ULONG fragment, UINT time_to_live, ULONG window_size,
95 VOID (*tcp_urgent_data_callback)(NX_TCP_SOCKET *socket_ptr),
96 VOID (*tcp_disconnect_callback)(NX_TCP_SOCKET *socket_ptr),
97 UINT tcp_socket_size)
98 {
99
100 UINT status;
101 NX_TCP_SOCKET *created_socket;
102 ULONG created_count;
103
104
105 /* Check for invalid input pointers. */
106 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) || (socket_ptr == NX_NULL) ||
107 (tcp_socket_size != (UINT)sizeof(NX_TCP_SOCKET)))
108 {
109 return(NX_PTR_ERROR);
110 }
111
112 /* Check for appropriate caller. */
113 NX_INIT_AND_THREADS_CALLER_CHECKING
114
115 /* Get protection mutex. */
116 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
117
118 /* Pickup created count and created socket pointer. */
119 created_count = ip_ptr -> nx_ip_tcp_created_sockets_count;
120 created_socket = ip_ptr -> nx_ip_tcp_created_sockets_ptr;
121
122 /* Loop to look for socket already created. */
123 while (created_count--)
124 {
125
126 /* Compare the new socket with the already created socket. */
127 if (socket_ptr == created_socket)
128 {
129
130 /* Error, socket already created! */
131
132 /* Release protection mutex. */
133 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
134
135 /* Return error. */
136 return(NX_PTR_ERROR);
137 }
138
139 /* Move to next created socket. */
140 created_socket = created_socket -> nx_tcp_socket_created_next;
141 }
142
143 /* Release protection mutex. */
144 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
145
146 /* Check to see if TCP is enabled. */
147 if (!ip_ptr -> nx_ip_tcp_packet_receive)
148 {
149 return(NX_NOT_ENABLED);
150 }
151
152 /* Check for valid type of service. */
153 if (type_of_service & ~(NX_IP_TOS_MASK))
154 {
155 return(NX_OPTION_ERROR);
156 }
157
158 /* Check for valid fragment option. */
159 if ((fragment != NX_FRAGMENT_OKAY) &&
160 (fragment != NX_DONT_FRAGMENT))
161 {
162 return(NX_OPTION_ERROR);
163 }
164
165 /* Check for valid time to live option. */
166 if (((ULONG)time_to_live) > NX_IP_TIME_TO_LIVE_MASK)
167 {
168 return(NX_OPTION_ERROR);
169 }
170
171 /* Check for valid window size. */
172 if (!window_size)
173 {
174 return(NX_OPTION_ERROR);
175 }
176
177 #ifndef NX_ENABLE_TCP_WINDOW_SCALING
178 if (window_size > NX_LOWER_16_MASK)
179 {
180 return(NX_OPTION_ERROR);
181 }
182 #else
183 /* The maximum scale exponent is limited to 14. Section 2.2, RFC 7323. */
184 if (window_size > ((1 << 30) - 1))
185 {
186 return(NX_OPTION_ERROR);
187 }
188 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
189
190 /* Call actual TCP socket create function. */
191 status = _nx_tcp_socket_create(ip_ptr, socket_ptr, name, type_of_service, fragment, time_to_live,
192 window_size, tcp_urgent_data_callback, tcp_disconnect_callback);
193
194 /* Return completion status. */
195 return(status);
196 }
197
198