]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c
Update the license dates
[mirror_edk2.git] / AppPkg / Applications / Sockets / SetSockOpt / SetSockOpt.c
CommitLineData
4684b66f 1/** @file\r
2 Set the socket options\r
3\r
9f7f5161 4 Copyright (c) 2011-2012, Intel Corporation\r
4684b66f 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
d3a595ce 195 default:\r
196 break;\r
197\r
4684b66f 198 case DATA_TYPE_INT32_DECIMAL:\r
199 Values = sscanf ( pValue, "%d", Value.i32 );\r
200 if ( 1 == Values ) {\r
201 BytesToWrite = sizeof ( *Value.i32);\r
202 errno = 0;\r
203 }\r
204 break;\r
205\r
206 case DATA_TYPE_TIMEVAL:\r
d3a595ce 207 Values = sscanf ( pValue, "%d.%d",\r
4684b66f 208 &Value.TimeVal->tv_sec,\r
209 &Value.TimeVal->tv_usec );\r
210 if (( 2 == Values )\r
211 && ( 0 <= Value.TimeVal->tv_sec )\r
212 && ( 0 <= Value.TimeVal->tv_usec )\r
213 && ( 1000000 > Value.TimeVal->tv_usec )){\r
214 BytesToWrite = sizeof ( *Value.TimeVal );\r
215 errno = 0;\r
216 }\r
217 }\r
218 }\r
219\r
220 //\r
221 // Display the error\r
222 //\r
223 if ( 0 == BytesToWrite ) {\r
224 Print ( L"ERROR - Invalid value!\r\n" );\r
225 }\r
226\r
227 //\r
228 // Return the number of bytes to be written\r
229 //\r
230 return BytesToWrite;\r
231}\r
232\r
233\r
234/**\r
235 Set the socket options\r
236\r
237 @param [in] Argc The number of arguments\r
238 @param [in] Argv The argument value array\r
239\r
240 @retval 0 The application exited normally.\r
241 @retval Other An error occurred.\r
242**/\r
243int\r
244main (\r
245 IN int Argc,\r
246 IN char **Argv\r
247 )\r
248{\r
249 socklen_t BytesToWrite;\r
250 socklen_t LengthInBytes;\r
251 CONST OPTIONS * pEnd;\r
252 CONST OPTIONS * pOption;\r
253 int s;\r
254 int Status;\r
255\r
256 DEBUG (( DEBUG_INFO,\r
257 "%a starting\r\n",\r
258 Argv[0]));\r
259\r
260 //\r
261 // Parse the socket option\r
262 //\r
263 pOption = &mOptions[0];\r
264 pEnd = &pOption[sizeof ( mOptions ) / sizeof ( mOptions[0])];\r
265 if ( 2 <= Argc ) {\r
266 while ( pEnd > pOption ) {\r
267 if ( 0 == strcmp ( Argv[1], pOption->pOptionName )) {\r
268 break;\r
269 }\r
270 pOption += 1;\r
271 }\r
272 if ( pEnd <= pOption ) {\r
273 Print ( L"ERROR: Invalid option: %a\r\n", Argv[1]);\r
274 Argc = 1;\r
275 }\r
276 }\r
277\r
278 //\r
279 // Display the help if necessary\r
280 //\r
281 if (( 2 > Argc ) || ( 3 < Argc )) {\r
282 Print ( L"%a <option>\r\n", Argv[0]);\r
283 Print ( L"\r\n" );\r
284 Print ( L"Option one of:\r\n" );\r
285 pOption = &mOptions[0];\r
286 while ( pEnd > pOption ) {\r
287 Print ( L" %a: %a\r\n",\r
288 pOption->pOptionName,\r
289 pOption->bSetAllowed ? "get/set" : "get" );\r
290 pOption += 1;\r
291 }\r
292 errno = EINVAL;\r
293 }\r
294 else {\r
295 //\r
296 // Determine if the value is to be set\r
297 //\r
298 BytesToWrite = 0;\r
299 if (( 3 > Argc )\r
59bc0593 300 || ( 0 < ( BytesToWrite = GetOptionValue ( pOption, Argv[2])))) {\r
4684b66f 301 //\r
302 // Get the socket\r
303 //\r
304 s = socket ( AF_INET, 0, 0 );\r
305 if ( -1 == s ) {\r
306 Print ( L"ERROR - Unable to open the socket, errno: %d\r\n", errno );\r
307 }\r
308 else {\r
309 //\r
310 // Display the option value\r
311 //\r
312 LengthInBytes = sizeof ( mBuffer );\r
313 Status = getsockopt ( s,\r
314 pOption->OptionLevel,\r
315 pOption->OptionValue,\r
316 &mBuffer,\r
317 &LengthInBytes );\r
318 if ( -1 == Status ) {\r
319 Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
320 }\r
321 else {\r
322 DisplayOption ( pOption,\r
323 LengthInBytes,\r
324 FALSE,\r
325 (BOOLEAN)( 0 == BytesToWrite ));\r
326\r
327 //\r
328 // Determine if the value is to be set\r
329 //\r
330 if (( 0 < BytesToWrite )\r
331 && ( BytesToWrite == LengthInBytes )) {\r
332 //\r
333 // Set the option value\r
334 //\r
335 Status = setsockopt ( s,\r
336 pOption->OptionLevel,\r
337 pOption->OptionValue,\r
338 &mValue,\r
339 BytesToWrite );\r
340 if ( -1 == Status ) {\r
341 Print ( L"ERROR - setsockopt failed, errno: %d\r\n", errno );\r
342 }\r
343 else {\r
344 //\r
345 // Display the updated option value\r
346 //\r
347 Status = getsockopt ( s,\r
348 pOption->OptionLevel,\r
349 pOption->OptionValue,\r
350 &mBuffer,\r
351 &LengthInBytes );\r
352 if ( -1 == Status ) {\r
353 Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
354 }\r
355 else {\r
356 DisplayOption ( pOption,\r
357 LengthInBytes,\r
358 TRUE,\r
359 TRUE );\r
360 }\r
361 }\r
362 }\r
363 }\r
364\r
365 //\r
366 // Done with the socket\r
367 //\r
368 close ( s );\r
369 }\r
370 }\r
371 }\r
372\r
373 //\r
374 // All done\r
375 //\r
376 DEBUG (( DEBUG_INFO,\r
377 "%a exiting, errno: %d\r\n",\r
378 Argv[0],\r
379 errno ));\r
380 return errno;\r
381}\r