diff options
Diffstat (limited to 'AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c')
-rw-r--r-- | AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c b/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c new file mode 100644 index 0000000000..fdc4552b60 --- /dev/null +++ b/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c @@ -0,0 +1,379 @@ +/** @file
+ Set the socket options
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <Uefi.h>
+#include <unistd.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+
+#include <sys/socket.h>
+#include <sys/time.h>
+
+typedef enum _DATA_TYPE {
+ DATA_TYPE_UNKNOWN = 0,
+ DATA_TYPE_INT32_DECIMAL,
+ DATA_TYPE_SOCKET_TYPE,
+ DATA_TYPE_TIMEVAL
+} DATA_TYPE;
+
+typedef struct {
+ char * pOptionName;
+ int OptionValue;
+ int OptionLevel;
+ BOOLEAN bSetAllowed;
+ DATA_TYPE DataType;
+} OPTIONS;
+
+CONST OPTIONS mOptions [] = {
+ { "SO_ACCEPTCONN", SO_ACCEPTCONN, SOL_SOCKET, FALSE, DATA_TYPE_UNKNOWN },
+ { "SO_BROADCAST", SO_BROADCAST, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_DEBUG", SO_DEBUG, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_DONTROUTE", SO_DONTROUTE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_ERROR", SO_ERROR, SOL_SOCKET, FALSE, DATA_TYPE_UNKNOWN },
+ { "SO_KEEPALIVE", SO_KEEPALIVE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_OOBINLINE", SO_OOBINLINE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_OVERFLOWED", SO_OVERFLOWED, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_RCVBUF", SO_RCVBUF, SOL_SOCKET, TRUE, DATA_TYPE_INT32_DECIMAL },
+ { "SO_RCVLOWAT", SO_RCVLOWAT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_RCVTIMEO", SO_RCVTIMEO, SOL_SOCKET, TRUE, DATA_TYPE_TIMEVAL },
+ { "SO_REUSEADDR", SO_REUSEADDR, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_REUSEPORT", SO_REUSEPORT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_SNDBUF", SO_SNDBUF, SOL_SOCKET, TRUE, DATA_TYPE_INT32_DECIMAL },
+ { "SO_SNDLOWAT", SO_SNDLOWAT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_SNDTIMEO", SO_SNDTIMEO, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_TIMESTAMP", SO_TIMESTAMP, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },
+ { "SO_TYPE", SO_TYPE, SOL_SOCKET, FALSE, DATA_TYPE_SOCKET_TYPE },
+ { "SO_USELOOPBACK", SO_USELOOPBACK, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN }
+};
+
+
+UINT8 mBuffer [ 65536 ];
+UINT8 mValue [ 65536 ];
+char * mSocketType [] = {
+ "SOCK_STREAM",
+ "SOCK_DGRAM",
+ "SOCK_RAW",
+ "SOCK_RDM",
+ "SOCK_SEQPACKET"
+};
+
+void
+DisplayOption (
+ CONST OPTIONS * pOption,
+ socklen_t LengthInBytes,
+ BOOLEAN bDisplayUpdate,
+ BOOLEAN bDisplayCrLf
+ )
+{
+ UINT8 * pEnd;
+ char * pString;
+ union {
+ UINT8 * u8;
+ INT32 * i32;
+ struct timeval * TimeVal;
+ } Value;
+
+ //
+ // Display the value length
+ //
+ if ( !bDisplayUpdate ) {
+ Print ( L"LengthInBytes: %d\r\n", LengthInBytes );
+ Print ( L"%a: ", pOption->pOptionName );
+ }
+ else {
+ Print ( L" --> " );
+ }
+
+ //
+ // Display the value
+ //
+ Value.u8 = &mBuffer[0];
+ switch ( pOption->DataType )
+ {
+ case DATA_TYPE_UNKNOWN:
+ Print ( L"%a:", pOption->pOptionName );
+ pEnd = &Value.u8 [ LengthInBytes ];
+ while ( pEnd > Value.u8 ) {
+ Print ( L" %02x", *Value.u8 );
+ Value.u8 += 1;
+ }
+ break;
+
+ case DATA_TYPE_INT32_DECIMAL:
+ if ( 4 == LengthInBytes ) {
+ Print ( L"%d", *Value.i32 );
+ }
+ else {
+ errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;
+ Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );
+ }
+ break;
+
+ case DATA_TYPE_SOCKET_TYPE:
+ if ( 4 == LengthInBytes ) {
+ if (( SOCK_STREAM <= *Value.i32 ) && ( SOCK_SEQPACKET >= *Value.i32 )) {
+ pString = mSocketType [ *Value.i32 - SOCK_STREAM ];
+ Print ( L"%a", pString );
+ }
+ else {
+ Print ( L"%08x (unknown type)", *Value.i32 );
+ }
+ }
+ else {
+ errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;
+ Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );
+ }
+ break;
+
+ case DATA_TYPE_TIMEVAL:
+ if ( sizeof ( *Value.TimeVal ) == LengthInBytes ) {
+ if (( 0 == Value.TimeVal->tv_sec )
+ && ( 0 == Value.TimeVal->tv_usec )) {
+ Print ( L"Infinite" );
+ }
+ else {
+ Print ( L"%d.%06d sec",
+ Value.TimeVal->tv_sec,
+ Value.TimeVal->tv_usec );
+ }
+ }
+ else {
+ errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;
+ Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );
+ }
+ break;
+ }
+
+ //
+ // Terminate the line
+ //
+ if ( bDisplayCrLf ) {
+ Print ( L"\r\n" );
+ }
+}
+
+socklen_t
+GetOptionValue (
+ CONST OPTIONS * pOption,
+ char * pValue
+ )
+{
+ socklen_t BytesToWrite;
+ union {
+ UINT8 * u8;
+ INT32 * i32;
+ struct timeval * TimeVal;
+ } Value;
+ int Values;
+
+ //
+ // Assume failure
+ //
+ errno = EINVAL;
+ BytesToWrite = 0;
+
+ //
+ // Determine the type of parameter
+ //
+ if ( pOption->bSetAllowed ) {
+ Value.u8 = &mValue[0];
+ switch ( pOption->DataType ) {
+ case DATA_TYPE_INT32_DECIMAL:
+ Values = sscanf ( pValue, "%d", Value.i32 );
+ if ( 1 == Values ) {
+ BytesToWrite = sizeof ( *Value.i32);
+ errno = 0;
+ }
+ break;
+
+ case DATA_TYPE_TIMEVAL:
+ Values = sscanf ( pValue, "%d.%0d",
+ &Value.TimeVal->tv_sec,
+ &Value.TimeVal->tv_usec );
+ if (( 2 == Values )
+ && ( 0 <= Value.TimeVal->tv_sec )
+ && ( 0 <= Value.TimeVal->tv_usec )
+ && ( 1000000 > Value.TimeVal->tv_usec )){
+ BytesToWrite = sizeof ( *Value.TimeVal );
+ errno = 0;
+ }
+ }
+ }
+
+ //
+ // Display the error
+ //
+ if ( 0 == BytesToWrite ) {
+ Print ( L"ERROR - Invalid value!\r\n" );
+ }
+
+ //
+ // Return the number of bytes to be written
+ //
+ return BytesToWrite;
+}
+
+
+/**
+ Set the socket options
+
+ @param [in] Argc The number of arguments
+ @param [in] Argv The argument value array
+
+ @retval 0 The application exited normally.
+ @retval Other An error occurred.
+**/
+int
+main (
+ IN int Argc,
+ IN char **Argv
+ )
+{
+ socklen_t BytesToWrite;
+ socklen_t LengthInBytes;
+ CONST OPTIONS * pEnd;
+ CONST OPTIONS * pOption;
+ int s;
+ int Status;
+
+ DEBUG (( DEBUG_INFO,
+ "%a starting\r\n",
+ Argv[0]));
+
+ //
+ // Parse the socket option
+ //
+ pOption = &mOptions[0];
+ pEnd = &pOption[sizeof ( mOptions ) / sizeof ( mOptions[0])];
+ if ( 2 <= Argc ) {
+ while ( pEnd > pOption ) {
+ if ( 0 == strcmp ( Argv[1], pOption->pOptionName )) {
+ break;
+ }
+ pOption += 1;
+ }
+ if ( pEnd <= pOption ) {
+ Print ( L"ERROR: Invalid option: %a\r\n", Argv[1]);
+ Argc = 1;
+ }
+ }
+
+ //
+ // Display the help if necessary
+ //
+ if (( 2 > Argc ) || ( 3 < Argc )) {
+ Print ( L"%a <option>\r\n", Argv[0]);
+ Print ( L"\r\n" );
+ Print ( L"Option one of:\r\n" );
+ pOption = &mOptions[0];
+ while ( pEnd > pOption ) {
+ Print ( L" %a: %a\r\n",
+ pOption->pOptionName,
+ pOption->bSetAllowed ? "get/set" : "get" );
+ pOption += 1;
+ }
+ errno = EINVAL;
+ }
+ else {
+ //
+ // Determine if the value is to be set
+ //
+ BytesToWrite = 0;
+ if (( 3 > Argc )
+ || ( 0 < ( BytesToWrite = GetOptionValue ( pOption, Argv [2])))) {
+ //
+ // Get the socket
+ //
+ s = socket ( AF_INET, 0, 0 );
+ if ( -1 == s ) {
+ Print ( L"ERROR - Unable to open the socket, errno: %d\r\n", errno );
+ }
+ else {
+ //
+ // Display the option value
+ //
+ LengthInBytes = sizeof ( mBuffer );
+ Status = getsockopt ( s,
+ pOption->OptionLevel,
+ pOption->OptionValue,
+ &mBuffer,
+ &LengthInBytes );
+ if ( -1 == Status ) {
+ Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );
+ }
+ else {
+ DisplayOption ( pOption,
+ LengthInBytes,
+ FALSE,
+ (BOOLEAN)( 0 == BytesToWrite ));
+
+ //
+ // Determine if the value is to be set
+ //
+ if (( 0 < BytesToWrite )
+ && ( BytesToWrite == LengthInBytes )) {
+ //
+ // Set the option value
+ //
+ Status = setsockopt ( s,
+ pOption->OptionLevel,
+ pOption->OptionValue,
+ &mValue,
+ BytesToWrite );
+ if ( -1 == Status ) {
+ Print ( L"ERROR - setsockopt failed, errno: %d\r\n", errno );
+ }
+ else {
+ //
+ // Display the updated option value
+ //
+ Status = getsockopt ( s,
+ pOption->OptionLevel,
+ pOption->OptionValue,
+ &mBuffer,
+ &LengthInBytes );
+ if ( -1 == Status ) {
+ Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );
+ }
+ else {
+ DisplayOption ( pOption,
+ LengthInBytes,
+ TRUE,
+ TRUE );
+ }
+ }
+ }
+ }
+
+ //
+ // Done with the socket
+ //
+ close ( s );
+ }
+ }
+ }
+
+ //
+ // All done
+ //
+ DEBUG (( DEBUG_INFO,
+ "%a exiting, errno: %d\r\n",
+ Argv[0],
+ errno ));
+ return errno;
+}
|