]> Chaos Git - corbenik/ctrulib.git/commitdiff
added SOCU_GetNetworkOpt
authorLectem <lectem@gmail.com>
Mon, 25 Jan 2016 00:38:29 +0000 (19:38 -0500)
committerLectem <lectem@gmail.com>
Mon, 25 Jan 2016 06:14:09 +0000 (01:14 -0500)
libctru/include/3ds/services/soc.h
libctru/source/services/soc/soc_getipinfo.c
libctru/source/services/soc/soc_getnetworkopt.c [new file with mode: 0644]

index dfb39d6d9151aaf3a725f1a428c2e41df935d929..26d68e8d74a30be46ff1782700dbf6a3844a6925 100644 (file)
@@ -6,6 +6,94 @@
  */
 #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.
@@ -35,6 +123,16 @@ int SOCU_ShutdownSockets();
 
 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
index a52c701f3c66ee7e8c10fcaa3079e63b588b3d31..84efe5ffa436b6712aacb9b460145c3b92a2bd87 100644 (file)
@@ -1,54 +1,14 @@
 #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;
diff --git a/libctru/source/services/soc/soc_getnetworkopt.c b/libctru/source/services/soc/soc_getnetworkopt.c
new file mode 100644 (file)
index 0000000..dc3f915
--- /dev/null
@@ -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;
+}