*/
#pragma once
#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.
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
* @return error
#include "soc_common.h"
#include <3ds/ipc.h>
#include <3ds/result.h>
-
-typedef struct
-{
- struct in_addr ip;
- struct in_addr netmask;
- struct in_addr broadcast;
-} SOCU_IPInfo_t;
+#include <3ds/services/soc.h>
int SOCU_GetIPInfo(struct in_addr *ip, struct in_addr *netmask, struct in_addr *broadcast)
{
- int i, ret;
- u32 *cmdbuf = getThreadCommandBuffer();
- u32 *staticbufs = getThreadStaticBuffers();
- u32 saved_threadstorage[2];
- 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];
- }
+ SOCU_IPInfo info;
+ socklen_t infolen = sizeof info;
+ int ret = SOCU_GetNetworkOpt(SOL_CONFIG,NETOPT_IP_INFO,&info,&infolen);
+ if(ret != 0) return ret;
if(ip != NULL)
*ip = info.ip;
--- /dev/null
+#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;
+}