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