]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c
Update the sockets library code
[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
42CONST OPTIONS mOptions [] = {\r
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
65UINT8 mBuffer [ 65536 ];\r
66UINT8 mValue [ 65536 ];\r
67char * mSocketType [] = {\r
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
106 switch ( pOption->DataType )\r
107 {\r
108 case DATA_TYPE_UNKNOWN:\r
109 Print ( L"%a:", pOption->pOptionName );\r
110 pEnd = &Value.u8 [ LengthInBytes ];\r
111 while ( pEnd > Value.u8 ) {\r
112 Print ( L" %02x", *Value.u8 );\r
113 Value.u8 += 1;\r
114 }\r
115 break;\r
116 \r
117 case DATA_TYPE_INT32_DECIMAL:\r
118 if ( 4 == LengthInBytes ) {\r
119 Print ( L"%d", *Value.i32 );\r
120 }\r
121 else {\r
122 errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
123 Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
124 }\r
125 break;\r
126\r
127 case DATA_TYPE_SOCKET_TYPE:\r
128 if ( 4 == LengthInBytes ) {\r
129 if (( SOCK_STREAM <= *Value.i32 ) && ( SOCK_SEQPACKET >= *Value.i32 )) {\r
130 pString = mSocketType [ *Value.i32 - SOCK_STREAM ];\r
131 Print ( L"%a", pString );\r
132 }\r
133 else {\r
134 Print ( L"%08x (unknown type)", *Value.i32 );\r
135 }\r
136 }\r
137 else {\r
138 errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
139 Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
140 }\r
141 break;\r
142\r
143 case DATA_TYPE_TIMEVAL:\r
144 if ( sizeof ( *Value.TimeVal ) == LengthInBytes ) {\r
145 if (( 0 == Value.TimeVal->tv_sec )\r
146 && ( 0 == Value.TimeVal->tv_usec )) {\r
147 Print ( L"Infinite" );\r
148 }\r
149 else {\r
150 Print ( L"%d.%06d sec",\r
151 Value.TimeVal->tv_sec,\r
152 Value.TimeVal->tv_usec );\r
153 }\r
154 }\r
155 else {\r
156 errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
157 Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
158 }\r
159 break;\r
160 }\r
161\r
162 //\r
163 // Terminate the line\r
164 //\r
165 if ( bDisplayCrLf ) {\r
166 Print ( L"\r\n" );\r
167 }\r
168}\r
169\r
170socklen_t\r
171GetOptionValue (\r
172 CONST OPTIONS * pOption,\r
173 char * pValue\r
174 )\r
175{\r
176 socklen_t BytesToWrite;\r
177 union {\r
178 UINT8 * u8;\r
179 INT32 * i32;\r
180 struct timeval * TimeVal;\r
181 } Value;\r
182 int Values;\r
183\r
184 //\r
185 // Assume failure\r
186 //\r
187 errno = EINVAL;\r
188 BytesToWrite = 0;\r
189\r
190 //\r
191 // Determine the type of parameter\r
192 //\r
193 if ( pOption->bSetAllowed ) {\r
194 Value.u8 = &mValue[0];\r
195 switch ( pOption->DataType ) {\r
196 case DATA_TYPE_INT32_DECIMAL:\r
197 Values = sscanf ( pValue, "%d", Value.i32 );\r
198 if ( 1 == Values ) {\r
199 BytesToWrite = sizeof ( *Value.i32);\r
200 errno = 0;\r
201 }\r
202 break;\r
203\r
204 case DATA_TYPE_TIMEVAL:\r
205 Values = sscanf ( pValue, "%d.%0d",\r
206 &Value.TimeVal->tv_sec,\r
207 &Value.TimeVal->tv_usec );\r
208 if (( 2 == Values )\r
209 && ( 0 <= Value.TimeVal->tv_sec )\r
210 && ( 0 <= Value.TimeVal->tv_usec )\r
211 && ( 1000000 > Value.TimeVal->tv_usec )){\r
212 BytesToWrite = sizeof ( *Value.TimeVal );\r
213 errno = 0;\r
214 }\r
215 }\r
216 }\r
217\r
218 //\r
219 // Display the error\r
220 //\r
221 if ( 0 == BytesToWrite ) {\r
222 Print ( L"ERROR - Invalid value!\r\n" );\r
223 }\r
224\r
225 //\r
226 // Return the number of bytes to be written\r
227 //\r
228 return BytesToWrite;\r
229}\r
230\r
231\r
232/**\r
233 Set the socket options\r
234\r
235 @param [in] Argc The number of arguments\r
236 @param [in] Argv The argument value array\r
237\r
238 @retval 0 The application exited normally.\r
239 @retval Other An error occurred.\r
240**/\r
241int\r
242main (\r
243 IN int Argc,\r
244 IN char **Argv\r
245 )\r
246{\r
247 socklen_t BytesToWrite;\r
248 socklen_t LengthInBytes;\r
249 CONST OPTIONS * pEnd;\r
250 CONST OPTIONS * pOption;\r
251 int s;\r
252 int Status;\r
253\r
254 DEBUG (( DEBUG_INFO,\r
255 "%a starting\r\n",\r
256 Argv[0]));\r
257\r
258 //\r
259 // Parse the socket option\r
260 //\r
261 pOption = &mOptions[0];\r
262 pEnd = &pOption[sizeof ( mOptions ) / sizeof ( mOptions[0])];\r
263 if ( 2 <= Argc ) {\r
264 while ( pEnd > pOption ) {\r
265 if ( 0 == strcmp ( Argv[1], pOption->pOptionName )) {\r
266 break;\r
267 }\r
268 pOption += 1;\r
269 }\r
270 if ( pEnd <= pOption ) {\r
271 Print ( L"ERROR: Invalid option: %a\r\n", Argv[1]);\r
272 Argc = 1;\r
273 }\r
274 }\r
275\r
276 //\r
277 // Display the help if necessary\r
278 //\r
279 if (( 2 > Argc ) || ( 3 < Argc )) {\r
280 Print ( L"%a <option>\r\n", Argv[0]);\r
281 Print ( L"\r\n" );\r
282 Print ( L"Option one of:\r\n" );\r
283 pOption = &mOptions[0];\r
284 while ( pEnd > pOption ) {\r
285 Print ( L" %a: %a\r\n",\r
286 pOption->pOptionName,\r
287 pOption->bSetAllowed ? "get/set" : "get" );\r
288 pOption += 1;\r
289 }\r
290 errno = EINVAL;\r
291 }\r
292 else {\r
293 //\r
294 // Determine if the value is to be set\r
295 //\r
296 BytesToWrite = 0;\r
297 if (( 3 > Argc )\r
298 || ( 0 < ( BytesToWrite = GetOptionValue ( pOption, Argv [2])))) {\r
299 //\r
300 // Get the socket\r
301 //\r
302 s = socket ( AF_INET, 0, 0 );\r
303 if ( -1 == s ) {\r
304 Print ( L"ERROR - Unable to open the socket, errno: %d\r\n", errno );\r
305 }\r
306 else {\r
307 //\r
308 // Display the option value\r
309 //\r
310 LengthInBytes = sizeof ( mBuffer );\r
311 Status = getsockopt ( s,\r
312 pOption->OptionLevel,\r
313 pOption->OptionValue,\r
314 &mBuffer,\r
315 &LengthInBytes );\r
316 if ( -1 == Status ) {\r
317 Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
318 }\r
319 else {\r
320 DisplayOption ( pOption,\r
321 LengthInBytes,\r
322 FALSE,\r
323 (BOOLEAN)( 0 == BytesToWrite ));\r
324\r
325 //\r
326 // Determine if the value is to be set\r
327 //\r
328 if (( 0 < BytesToWrite )\r
329 && ( BytesToWrite == LengthInBytes )) {\r
330 //\r
331 // Set the option value\r
332 //\r
333 Status = setsockopt ( s,\r
334 pOption->OptionLevel,\r
335 pOption->OptionValue,\r
336 &mValue,\r
337 BytesToWrite );\r
338 if ( -1 == Status ) {\r
339 Print ( L"ERROR - setsockopt failed, errno: %d\r\n", errno );\r
340 }\r
341 else {\r
342 //\r
343 // Display the updated option value\r
344 //\r
345 Status = getsockopt ( s,\r
346 pOption->OptionLevel,\r
347 pOption->OptionValue,\r
348 &mBuffer,\r
349 &LengthInBytes );\r
350 if ( -1 == Status ) {\r
351 Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
352 }\r
353 else {\r
354 DisplayOption ( pOption,\r
355 LengthInBytes,\r
356 TRUE,\r
357 TRUE );\r
358 }\r
359 }\r
360 }\r
361 }\r
362\r
363 //\r
364 // Done with the socket\r
365 //\r
366 close ( s );\r
367 }\r
368 }\r
369 }\r
370\r
371 //\r
372 // All done\r
373 //\r
374 DEBUG (( DEBUG_INFO,\r
375 "%a exiting, errno: %d\r\n",\r
376 Argv[0],\r
377 errno ));\r
378 return errno;\r
379}\r