added SOCU_GetNetworkOpt

This commit is contained in:
Lectem 2016-01-24 19:38:29 -05:00
parent 3a3ee64b64
commit 2b9dc3c82a
3 changed files with 157 additions and 45 deletions

View File

@ -6,6 +6,94 @@
*/ */
#pragma once #pragma once
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h>
/// The config level to be used with @ref SOCU_GetNetworkOpt
#define SOL_CONFIG 0xfffe
/// Options to be used with @ref SOCU_GetNetworkOpt
typedef enum
{
NETOPT_MAC_ADDRESS = 0x1004, ///< The mac address of the interface (u32 mac[6])
NETOPT_ARP_TABLE = 0x3002, ///< The ARP table @see SOCU_ARPTableEntry
NETOPT_IP_INFO = 0x4003, ///< The cureent IP setup @see SOCU_IPInfo
NETOPT_IP_MTU = 0x4004, ///< The value of the IP MTU (u32)
NETOPT_ROUTING_TABLE = 0x4006, ///< The routing table @see SOCU_RoutingTableEntry
NETOPT_UDP_NUMBER = 0x8002, ///< The number of sockets in the UDP table (u32)
NETOPT_UDP_TABLE = 0x8003, ///< The table of opened UDP sockets @see SOCU_UDPTableEntry
NETOPT_TCP_NUMBER = 0x9002, ///< The number of sockets in the TCP table (u32)
NETOPT_TCP_TABLE = 0x9003, ///< The table of opened TCP sockets @see SOCU_TCPTableEntry
NETOPT_DNS_TABLE = 0xB003, ///< The table of the DNS servers @see SOCU_DNSTableEntry -- Returns a buffer of size 336 but only 2 entries are set ?
} NetworkOpt;
/// One entry of the ARP table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_ARP_TABLE
typedef struct
{
u32 unk0; // often 2 ? state ?
struct in_addr ip; ///< The IPv4 address associated to the entry
u8 mac[6]; ///< The MAC address of associated to the entry
u8 padding[2];
} SOCU_ARPTableEntry;
/// Structure returned by @ref SOCU_GetNetworkOpt when using @ref NETOPT_IP_INFO
typedef struct
{
struct in_addr ip; ///< Current IPv4 address
struct in_addr netmask; ///< Current network mask
struct in_addr broadcast; ///< Current network broadcast address
} SOCU_IPInfo;
// Linux netstat flags
// NOTE : there are probably other flags supported, if you can forge ICMP requests please check for D and M flags
/** The route uses a gateway */
#define ROUTING_FLAG_G 0x01
/// One entry of the routing table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_ROUTING_TABLE
typedef struct
{
struct in_addr dest_ip; ///< Destination IP address of the route
struct in_addr netmask; ///< Mask used for this route
struct in_addr gateway; ///< Gateway address to reach the network
u32 flags; ///< Linux netstat flags @see ROUTING_FLAG_G
u64 time; ///< number of milliseconds since 1st Jan 1900 00:00.
} SOCU_RoutingTableEntry;
/// One entry of the UDP sockets table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_UDP_TABLE
typedef struct
{
struct sockaddr_storage local; ///< Local address information
struct sockaddr_storage remote; ///< Remote address information
} SOCU_UDPTableEntry;
///@name TCP states
///@{
#define TCP_STATE_CLOSED 1
#define TCP_STATE_LISTEN 2
#define TCP_STATE_ESTABLISHED 5
#define TCP_STATE_FINWAIT1 6
#define TCP_STATE_FINWAIT2 7
#define TCP_STATE_CLOSE_WAIT 8
#define TCP_STATE_LAST_ACK 9
#define TCP_STATE_TIME_WAIT 11
///@}
/// One entry of the TCP sockets table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_TCP_TABLE
typedef struct
{
u32 state; ///< @see TCP states defines
struct sockaddr_storage local; ///< Local address information
struct sockaddr_storage remote; ///< Remote address information
} SOCU_TCPTableEntry;
/// One entry of the DNS servers table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_DNS_TABLE
typedef struct
{
u32 family; /// Family of the address of the DNS server
struct in_addr ip; /// IP of the DNS server
u8 padding[12]; // matches the length required for IPv6 addresses
} SOCU_DNSTableEntry;
/** /**
* @brief Initializes the SOC service. * @brief Initializes the SOC service.
@ -35,6 +123,16 @@ int SOCU_ShutdownSockets();
int SOCU_CloseSockets(); int SOCU_CloseSockets();
/**
* @brief Retrieves information from the network configuration. Similar to getsockopt().
* @param level Only value allowed seems to be @ref SOL_CONFIG
* @param optname The option to be retrieved
* @param optval Will contain the output of the command
* @param optlen Size of the optval buffer, will be updated to hold the size of the output
* @return 0 if successful. -1 if failed, and errno will be set accordingly. Can also return a system error code.
*/
int SOCU_GetNetworkOpt(int level, NetworkOpt optname, void * optval, socklen_t * optlen);
/** /**
* @brief Gets the system's IP address, netmask, and subnet broadcast * @brief Gets the system's IP address, netmask, and subnet broadcast
* @return error * @return error

View File

@ -1,54 +1,14 @@
#include "soc_common.h" #include "soc_common.h"
#include <3ds/ipc.h> #include <3ds/ipc.h>
#include <3ds/result.h> #include <3ds/result.h>
#include <3ds/services/soc.h>
typedef struct
{
struct in_addr ip;
struct in_addr netmask;
struct in_addr broadcast;
} SOCU_IPInfo_t;
int SOCU_GetIPInfo(struct in_addr *ip, struct in_addr *netmask, struct in_addr *broadcast) int SOCU_GetIPInfo(struct in_addr *ip, struct in_addr *netmask, struct in_addr *broadcast)
{ {
int i, ret; SOCU_IPInfo info;
u32 *cmdbuf = getThreadCommandBuffer(); socklen_t infolen = sizeof info;
u32 *staticbufs = getThreadStaticBuffers(); int ret = SOCU_GetNetworkOpt(SOL_CONFIG,NETOPT_IP_INFO,&info,&infolen);
u32 saved_threadstorage[2]; if(ret != 0) return ret;
SOCU_IPInfo_t info;
cmdbuf[0] = IPC_MakeHeader(0x1A,3,0); //0x1A00C0
cmdbuf[1] = 0xFFFE;
cmdbuf[2] = 0x4003;
cmdbuf[3] = sizeof(info);
// Save the thread storage values
for(i = 0 ; i < 2 ; ++i)
saved_threadstorage[i] = staticbufs[i];
staticbufs[0] = IPC_Desc_StaticBuffer(sizeof(info), 0);
staticbufs[1] = (u32)&info;
ret = svcSendSyncRequest(SOCU_handle);
// Restore the thread storage values
for(i = 0 ; i < 2 ; ++i)
staticbufs[i] = saved_threadstorage[i];
if(R_FAILED(ret)) {
errno = SYNC_ERROR;
return ret;
}
ret = cmdbuf[1];
if(R_FAILED(ret)) {
errno = SYNC_ERROR;
return ret;
}
if(cmdbuf[2] != 0)
{
return cmdbuf[2];
}
if(ip != NULL) if(ip != NULL)
*ip = info.ip; *ip = info.ip;

View File

@ -0,0 +1,54 @@
#include "soc_common.h"
#include <3ds/ipc.h>
#include <3ds/result.h>
#include <3ds/services/soc.h>
int SOCU_GetNetworkOpt(int level, NetworkOpt optname, void * optval, socklen_t * optlen)
{
int i, ret;
u32 *cmdbuf = getThreadCommandBuffer();
u32 *staticbufs = getThreadStaticBuffers();
u32 saved_threadstorage[2];
cmdbuf[0] = IPC_MakeHeader(0x1A,3,0); //0x1A00C0
cmdbuf[1] = level;
cmdbuf[2] = optname;
cmdbuf[3] = *optlen;
// Save the thread storage values
for(i = 0 ; i < 2 ; ++i)
saved_threadstorage[i] = staticbufs[i];
staticbufs[0] = IPC_Desc_StaticBuffer(*optlen, 0);
staticbufs[1] = (u32)optval;
ret = svcSendSyncRequest(SOCU_handle);
// Restore the thread storage values
for(i = 0 ; i < 2 ; ++i)
staticbufs[i] = saved_threadstorage[i];
if(R_FAILED(ret)) {
errno = SYNC_ERROR;
return ret;
}
ret = (int)cmdbuf[1];
if(R_FAILED(ret))
{
errno = SYNC_ERROR;
return ret;
}
ret = _net_convert_error(cmdbuf[2]);
if(ret < 0) {
errno = -ret;
return -1;
}
*optlen = cmdbuf[3];
return ret;
}