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