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