Add Socket Library applications.
Modify AppPkg.dsc file to include StdLib.inc which contains the Boilerplate text for Standard Library based Applications. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12062 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
379
AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c
Normal file
379
AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c
Normal file
@ -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;
|
||||
}
|
Reference in New Issue
Block a user