]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c
AppPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / AppPkg / Applications / Sockets / SetSockOpt / SetSockOpt.c
CommitLineData
4684b66f 1/** @file\r
2 Set the socket options\r
3\r
bcb96695
MK
4 Copyright (c) 2011-2012, Intel Corporation. All rights reserved.\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
4684b66f 6\r
7**/\r
8\r
9#include <errno.h>\r
10#include <stdio.h>\r
11#include <string.h>\r
12#include <Uefi.h>\r
13#include <unistd.h>\r
14\r
15#include <Library/DebugLib.h>\r
16#include <Library/UefiLib.h>\r
17\r
18#include <sys/socket.h>\r
19#include <sys/time.h>\r
20\r
21typedef enum _DATA_TYPE {\r
22 DATA_TYPE_UNKNOWN = 0,\r
23 DATA_TYPE_INT32_DECIMAL,\r
24 DATA_TYPE_SOCKET_TYPE,\r
25 DATA_TYPE_TIMEVAL\r
26} DATA_TYPE;\r
27\r
28typedef struct {\r
29 char * pOptionName;\r
30 int OptionValue;\r
31 int OptionLevel;\r
32 BOOLEAN bSetAllowed;\r
33 DATA_TYPE DataType;\r
34} OPTIONS;\r
35\r
59bc0593 36CONST OPTIONS mOptions[] = {\r
4684b66f 37 { "SO_ACCEPTCONN", SO_ACCEPTCONN, SOL_SOCKET, FALSE, DATA_TYPE_UNKNOWN },\r
38 { "SO_BROADCAST", SO_BROADCAST, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
39 { "SO_DEBUG", SO_DEBUG, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
40 { "SO_DONTROUTE", SO_DONTROUTE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
41 { "SO_ERROR", SO_ERROR, SOL_SOCKET, FALSE, DATA_TYPE_UNKNOWN },\r
42 { "SO_KEEPALIVE", SO_KEEPALIVE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
43 { "SO_OOBINLINE", SO_OOBINLINE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
44 { "SO_OVERFLOWED", SO_OVERFLOWED, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
45 { "SO_RCVBUF", SO_RCVBUF, SOL_SOCKET, TRUE, DATA_TYPE_INT32_DECIMAL },\r
46 { "SO_RCVLOWAT", SO_RCVLOWAT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
47 { "SO_RCVTIMEO", SO_RCVTIMEO, SOL_SOCKET, TRUE, DATA_TYPE_TIMEVAL },\r
48 { "SO_REUSEADDR", SO_REUSEADDR, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
49 { "SO_REUSEPORT", SO_REUSEPORT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
50 { "SO_SNDBUF", SO_SNDBUF, SOL_SOCKET, TRUE, DATA_TYPE_INT32_DECIMAL },\r
51 { "SO_SNDLOWAT", SO_SNDLOWAT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
52 { "SO_SNDTIMEO", SO_SNDTIMEO, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
53 { "SO_TIMESTAMP", SO_TIMESTAMP, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
54 { "SO_TYPE", SO_TYPE, SOL_SOCKET, FALSE, DATA_TYPE_SOCKET_TYPE },\r
55 { "SO_USELOOPBACK", SO_USELOOPBACK, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN }\r
56};\r
57\r
58\r
59bc0593 59UINT8 mBuffer[ 65536 ];\r
60UINT8 mValue[ 65536 ];\r
61char * mSocketType[] = {\r
4684b66f 62 "SOCK_STREAM",\r
63 "SOCK_DGRAM",\r
64 "SOCK_RAW",\r
65 "SOCK_RDM",\r
66 "SOCK_SEQPACKET"\r
67};\r
68\r
69void\r
70DisplayOption (\r
71 CONST OPTIONS * pOption,\r
72 socklen_t LengthInBytes,\r
73 BOOLEAN bDisplayUpdate,\r
74 BOOLEAN bDisplayCrLf\r
75 )\r
76{\r
77 UINT8 * pEnd;\r
78 char * pString;\r
79 union {\r
80 UINT8 * u8;\r
81 INT32 * i32;\r
82 struct timeval * TimeVal;\r
83 } Value;\r
84\r
85 //\r
86 // Display the value length\r
87 //\r
88 if ( !bDisplayUpdate ) {\r
89 Print ( L"LengthInBytes: %d\r\n", LengthInBytes );\r
90 Print ( L"%a: ", pOption->pOptionName );\r
91 }\r
92 else {\r
93 Print ( L" --> " );\r
94 }\r
95\r
96 //\r
97 // Display the value\r
98 //\r
99 Value.u8 = &mBuffer[0];\r
59bc0593 100 switch ( pOption->DataType ) {\r
4684b66f 101 case DATA_TYPE_UNKNOWN:\r
102 Print ( L"%a:", pOption->pOptionName );\r
59bc0593 103 pEnd = &Value.u8[ LengthInBytes ];\r
4684b66f 104 while ( pEnd > Value.u8 ) {\r
105 Print ( L" %02x", *Value.u8 );\r
106 Value.u8 += 1;\r
107 }\r
108 break;\r
109 \r
110 case DATA_TYPE_INT32_DECIMAL:\r
111 if ( 4 == LengthInBytes ) {\r
112 Print ( L"%d", *Value.i32 );\r
113 }\r
114 else {\r
115 errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
116 Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
117 }\r
118 break;\r
119\r
120 case DATA_TYPE_SOCKET_TYPE:\r
121 if ( 4 == LengthInBytes ) {\r
122 if (( SOCK_STREAM <= *Value.i32 ) && ( SOCK_SEQPACKET >= *Value.i32 )) {\r
59bc0593 123 pString = mSocketType[ *Value.i32 - SOCK_STREAM ];\r
4684b66f 124 Print ( L"%a", pString );\r
125 }\r
126 else {\r
127 Print ( L"%08x (unknown type)", *Value.i32 );\r
128 }\r
129 }\r
130 else {\r
131 errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
132 Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
133 }\r
134 break;\r
135\r
136 case DATA_TYPE_TIMEVAL:\r
137 if ( sizeof ( *Value.TimeVal ) == LengthInBytes ) {\r
138 if (( 0 == Value.TimeVal->tv_sec )\r
139 && ( 0 == Value.TimeVal->tv_usec )) {\r
140 Print ( L"Infinite" );\r
141 }\r
142 else {\r
143 Print ( L"%d.%06d sec",\r
144 Value.TimeVal->tv_sec,\r
145 Value.TimeVal->tv_usec );\r
146 }\r
147 }\r
148 else {\r
149 errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
150 Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
151 }\r
152 break;\r
153 }\r
154\r
155 //\r
156 // Terminate the line\r
157 //\r
158 if ( bDisplayCrLf ) {\r
159 Print ( L"\r\n" );\r
160 }\r
161}\r
162\r
163socklen_t\r
164GetOptionValue (\r
165 CONST OPTIONS * pOption,\r
166 char * pValue\r
167 )\r
168{\r
169 socklen_t BytesToWrite;\r
170 union {\r
171 UINT8 * u8;\r
172 INT32 * i32;\r
173 struct timeval * TimeVal;\r
174 } Value;\r
175 int Values;\r
176\r
177 //\r
178 // Assume failure\r
179 //\r
180 errno = EINVAL;\r
181 BytesToWrite = 0;\r
182\r
183 //\r
184 // Determine the type of parameter\r
185 //\r
186 if ( pOption->bSetAllowed ) {\r
187 Value.u8 = &mValue[0];\r
188 switch ( pOption->DataType ) {\r
d3a595ce 189 default:\r
190 break;\r
191\r
4684b66f 192 case DATA_TYPE_INT32_DECIMAL:\r
193 Values = sscanf ( pValue, "%d", Value.i32 );\r
194 if ( 1 == Values ) {\r
195 BytesToWrite = sizeof ( *Value.i32);\r
196 errno = 0;\r
197 }\r
198 break;\r
199\r
200 case DATA_TYPE_TIMEVAL:\r
d3a595ce 201 Values = sscanf ( pValue, "%d.%d",\r
4684b66f 202 &Value.TimeVal->tv_sec,\r
203 &Value.TimeVal->tv_usec );\r
204 if (( 2 == Values )\r
205 && ( 0 <= Value.TimeVal->tv_sec )\r
206 && ( 0 <= Value.TimeVal->tv_usec )\r
207 && ( 1000000 > Value.TimeVal->tv_usec )){\r
208 BytesToWrite = sizeof ( *Value.TimeVal );\r
209 errno = 0;\r
210 }\r
211 }\r
212 }\r
213\r
214 //\r
215 // Display the error\r
216 //\r
217 if ( 0 == BytesToWrite ) {\r
218 Print ( L"ERROR - Invalid value!\r\n" );\r
219 }\r
220\r
221 //\r
222 // Return the number of bytes to be written\r
223 //\r
224 return BytesToWrite;\r
225}\r
226\r
227\r
228/**\r
229 Set the socket options\r
230\r
231 @param [in] Argc The number of arguments\r
232 @param [in] Argv The argument value array\r
233\r
234 @retval 0 The application exited normally.\r
235 @retval Other An error occurred.\r
236**/\r
237int\r
238main (\r
239 IN int Argc,\r
240 IN char **Argv\r
241 )\r
242{\r
243 socklen_t BytesToWrite;\r
244 socklen_t LengthInBytes;\r
245 CONST OPTIONS * pEnd;\r
246 CONST OPTIONS * pOption;\r
247 int s;\r
248 int Status;\r
249\r
250 DEBUG (( DEBUG_INFO,\r
251 "%a starting\r\n",\r
252 Argv[0]));\r
253\r
254 //\r
255 // Parse the socket option\r
256 //\r
257 pOption = &mOptions[0];\r
258 pEnd = &pOption[sizeof ( mOptions ) / sizeof ( mOptions[0])];\r
259 if ( 2 <= Argc ) {\r
260 while ( pEnd > pOption ) {\r
261 if ( 0 == strcmp ( Argv[1], pOption->pOptionName )) {\r
262 break;\r
263 }\r
264 pOption += 1;\r
265 }\r
266 if ( pEnd <= pOption ) {\r
267 Print ( L"ERROR: Invalid option: %a\r\n", Argv[1]);\r
268 Argc = 1;\r
269 }\r
270 }\r
271\r
272 //\r
273 // Display the help if necessary\r
274 //\r
275 if (( 2 > Argc ) || ( 3 < Argc )) {\r
276 Print ( L"%a <option>\r\n", Argv[0]);\r
277 Print ( L"\r\n" );\r
278 Print ( L"Option one of:\r\n" );\r
279 pOption = &mOptions[0];\r
280 while ( pEnd > pOption ) {\r
281 Print ( L" %a: %a\r\n",\r
282 pOption->pOptionName,\r
283 pOption->bSetAllowed ? "get/set" : "get" );\r
284 pOption += 1;\r
285 }\r
286 errno = EINVAL;\r
287 }\r
288 else {\r
289 //\r
290 // Determine if the value is to be set\r
291 //\r
292 BytesToWrite = 0;\r
293 if (( 3 > Argc )\r
59bc0593 294 || ( 0 < ( BytesToWrite = GetOptionValue ( pOption, Argv[2])))) {\r
4684b66f 295 //\r
296 // Get the socket\r
297 //\r
298 s = socket ( AF_INET, 0, 0 );\r
299 if ( -1 == s ) {\r
300 Print ( L"ERROR - Unable to open the socket, errno: %d\r\n", errno );\r
301 }\r
302 else {\r
303 //\r
304 // Display the option value\r
305 //\r
306 LengthInBytes = sizeof ( mBuffer );\r
307 Status = getsockopt ( s,\r
308 pOption->OptionLevel,\r
309 pOption->OptionValue,\r
310 &mBuffer,\r
311 &LengthInBytes );\r
312 if ( -1 == Status ) {\r
313 Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
314 }\r
315 else {\r
316 DisplayOption ( pOption,\r
317 LengthInBytes,\r
318 FALSE,\r
319 (BOOLEAN)( 0 == BytesToWrite ));\r
320\r
321 //\r
322 // Determine if the value is to be set\r
323 //\r
324 if (( 0 < BytesToWrite )\r
325 && ( BytesToWrite == LengthInBytes )) {\r
326 //\r
327 // Set the option value\r
328 //\r
329 Status = setsockopt ( s,\r
330 pOption->OptionLevel,\r
331 pOption->OptionValue,\r
332 &mValue,\r
333 BytesToWrite );\r
334 if ( -1 == Status ) {\r
335 Print ( L"ERROR - setsockopt failed, errno: %d\r\n", errno );\r
336 }\r
337 else {\r
338 //\r
339 // Display the updated option value\r
340 //\r
341 Status = getsockopt ( s,\r
342 pOption->OptionLevel,\r
343 pOption->OptionValue,\r
344 &mBuffer,\r
345 &LengthInBytes );\r
346 if ( -1 == Status ) {\r
347 Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
348 }\r
349 else {\r
350 DisplayOption ( pOption,\r
351 LengthInBytes,\r
352 TRUE,\r
353 TRUE );\r
354 }\r
355 }\r
356 }\r
357 }\r
358\r
359 //\r
360 // Done with the socket\r
361 //\r
362 close ( s );\r
363 }\r
364 }\r
365 }\r
366\r
367 //\r
368 // All done\r
369 //\r
370 DEBUG (( DEBUG_INFO,\r
371 "%a exiting, errno: %d\r\n",\r
372 Argv[0],\r
373 errno ));\r
374 return errno;\r
375}\r