libnx  v4.8.0
lp2p.h
Go to the documentation of this file.
1 /**
2  * @file lp2p.h
3  * @brief lp2p service IPC wrapper, for local-WLAN communications with accessories. See also: https://switchbrew.org/wiki/LDN_services
4  * @note Only available on [9.1.0+].
5  * @author yellows8
6  * @copyright libnx Authors
7  */
8 
9 #pragma once
10 #include "../types.h"
11 #include "../sf/service.h"
12 #include "../kernel/event.h"
13 
14 typedef enum {
15  Lp2pServiceType_App = 0, ///< Initializes lp2p:app.
16  Lp2pServiceType_System = 1, ///< Initializes lp2p:sys.
18 
19 /// MacAddress
20 typedef struct {
21  u8 addr[6]; ///< Address
23 
24 /// GroupId
25 typedef struct {
26  u8 id[0x6]; ///< BSSID
27 } Lp2pGroupId;
28 
29 /// GroupInfo
30 /// \ref lp2pScan only uses the following fields for the cmd input struct: supported_platform/priority, frequency/channel, and preshared_key_binary_size/preshared_key.
31 typedef struct {
32  u8 unk_x0[0x10]; ///< When zero, this is set to randomly-generated data. Used during key derivation.
33  u64 local_communication_id; ///< LocalCommunicationId. When zero, the value from the user-process control.nacp is loaded. This is later validated by \ref lp2pJoin / \ref lp2pCreateGroup the same way as LdnNetworkConfig::local_communication_id. Used during key derivation.
34  Lp2pGroupId group_id; ///< Should be all-zero for the input struct so that the default is used.
35  char service_name[0x21]; ///< ServiceName. NUL-terminated string for the SSID. These characters must be '-' or alphanumeric (lowercase/uppercase). '_' must not be used, unless you generate valid data for that. The data for '_' will be automatically generated if it's not present.
36  s8 flags_count; ///< Must be <=0x3F.
37  s8 flags[0x40]; ///< Array of s8 with the above count. Each entry value must be <=0x3F. Each entry is an array index used to load a set of flags from a global array with the specified index.
38  u8 supported_platform; ///< SupportedPlatform. Must match value 1. 0 is PlatformIdNX, 1 is PlatformIdFuji.
39  s8 member_count_max; ///< MemberCountMax. Must be <=0x8. If zero during group-creation, a default of value 1 is used for the value passed to a service-cmd.
40  u8 unk_x82; ///< Unknown
41  u8 unk_x83; ///< Unknown
42  u16 frequency; ///< Wifi frequency: 24 = 2.4GHz, 50 = 5GHz.
43  s16 channel; ///< Wifi channel number. 0 = use default, otherwise this must be one of the following depending on the frequency field. 24: 1, 6, 11. 50: 36, 40, 44, 48.
44  u8 network_mode; ///< NetworkMode
45  u8 performance_requirement; ///< PerformanceRequirement
46  u8 security_type; ///< Security type, used during key derivation. 0 = use defaults, 1 = plaintext, 2 = encrypted. [11.0.0+] 3: Standard WPA2-PSK.
47  s8 static_aes_key_index; ///< StaticAesKeyIndex. Used as the array-index for selecting the KeySource used with GenerateAesKek during key derivation. Should be 1-2, otherwise GenerateAesKek is skipped and zeros are used for the AccessKey instead.
48  u8 unk_x8C; ///< Unknown
49  u8 priority; ///< Priority. Must match one of the following, depending on the used service (doesn't apply to \ref lp2pJoin): 55 = SystemPriority (lp2p:sys), 90 = ApplicationPriority (lp2p:app and lp2p:sys).
50  u8 stealth_enabled; ///< StealthEnabled. Bool flag, controls whether the SSID is hidden.
51  u8 unk_x8F; ///< If zero, a default value of 0x20 is used.
52  u8 unk_x90[0x130]; ///< Unknown
53  u8 preshared_key_binary_size; ///< PresharedKeyBinarySize
54  u8 preshared_key[0x3F]; ///< PresharedKey. Used during key derivation.
56 
57 /// ScanResult
58 typedef struct {
59  Lp2pGroupInfo group_info; ///< \ref Lp2pGroupInfo
60  u8 unk_x200; ///< Unknown
61  u8 unk_x201[0x5]; ///< Unknown
62  u16 advertise_data_size; ///< Size of the following AdvertiseData.
63  u8 advertise_data[0x80]; ///< AdvertiseData, with the above size. This originates from \ref lp2pSetAdvertiseData.
64  u8 unk_x288[0x78]; ///< Unknown
66 
67 /// NodeInfo
68 typedef struct {
69  u8 ip_addr[0x20]; ///< struct sockaddr for the IP address.
70  u8 unk_x20[0x4]; ///< Unknown
71  Lp2pMacAddress mac_addr; ///< \ref Lp2pMacAddress
72  u8 unk_x2A[0x56]; ///< Unknown
73 } Lp2pNodeInfo;
74 
75 /// IpConfig. Only contains IPv4 addresses.
76 typedef struct {
77  u8 unk_x0[0x20]; ///< Always zeros.
78  u8 ip_addr[0x20]; ///< struct sockaddr for the IP address.
79  u8 subnet_mask[0x20]; ///< struct sockaddr for the subnet-mask.
80  u8 gateway[0x20]; ///< struct sockaddr for the gateway(?).
81  u8 unk_x80[0x80]; ///< Always zeros.
82 } Lp2pIpConfig;
83 
84 /// Initialize lp2p.
86 
87 /// Exit lp2p.
88 void lp2pExit(void);
89 
90 /// Gets the Service object for INetworkService.
92 
93 /// Gets the Service object for INetworkServiceMonitor.
95 
96 /**
97  * @brief Creates a default \ref Lp2pGroupInfo for use with \ref lp2pCreateGroup / \ref lp2pJoin.
98  * @param info \ref Lp2pGroupInfo
99  */
101 
102 /**
103  * @brief Creates a default \ref Lp2pGroupInfo for use with \ref lp2pScan.
104  * @param info \ref Lp2pGroupInfo
105  */
107 
108 /**
109  * @brief Sets Lp2pGroupInfo::service_name.
110  * @param info \ref Lp2pGroupInfo
111  * @param[in] name ServiceName / SSID.
112  */
113 void lp2pGroupInfoSetServiceName(Lp2pGroupInfo *info, const char *name);
114 
115 /**
116  * @brief Sets Lp2pGroupInfo::flags_count and Lp2pGroupInfo::flags.
117  * @note The default is count=1 flags[0]=1, which is used by \ref lp2pCreateGroupInfo. [11.0.0+] To use standard WPA2-PSK, you can use flags[0]=0.
118  * @param info \ref Lp2pGroupInfo
119  * @param[in] flags Lp2pGroupInfo::flags
120  * @param[in] count Lp2pGroupInfo::flags_count
121  */
122 void lp2pGroupInfoSetFlags(Lp2pGroupInfo *info, s8 *flags, size_t count);
123 
124 /**
125  * @brief Sets Lp2pGroupInfo::member_count_max.
126  * @param info \ref Lp2pGroupInfo
127  * @param[in] count MemberCountMax
128  */
130  info->member_count_max = count;
131 }
132 
133 /**
134  * @brief Sets Lp2pGroupInfo::frequency and Lp2pGroupInfo::channel.
135  * @param info \ref Lp2pGroupInfo
136  * @param[in] frequency Lp2pGroupInfo::frequency
137  * @param[in] channel Lp2pGroupInfo::channel
138  */
140  info->frequency = frequency;
141  info->channel = channel;
142 }
143 
144 /**
145  * @brief Sets Lp2pGroupInfo::stealth_enabled.
146  * @param info \ref Lp2pGroupInfo
147  * @param[in] flag Lp2pGroupInfo::stealth_enabled
148  */
150  info->stealth_enabled = flag!=0;
151 }
152 
153 /**
154  * @brief Sets the PresharedKey for the specified \ref Lp2pGroupInfo.
155  * @note Using this is required before using the \ref Lp2pGroupInfo as input for any cmds, so that Lp2pGroupInfo::preshared_key_binary_size gets initialized.
156  * @note If standard WPA2-PSK is being used, use \ref lp2pGroupInfoSetPassphrase instead.
157  * @param info \ref Lp2pGroupInfo
158  * @param[in] key Data for the PresharedKey.
159  * @param[in] size Size to copy into the PresharedKey, max is 0x20.
160  */
161 void lp2pGroupInfoSetPresharedKey(Lp2pGroupInfo *info, const void* key, size_t size);
162 
163 /**
164  * @brief Sets the passphrase, for when standard WPA2-PSK is being used.
165  * @note Configure standard WPA2-PSK usage via \ref lp2pGroupInfoSetFlags / Lp2pGroupInfo::security_type.
166  * @note Only available on [11.0.0+].
167  * @param info \ref Lp2pGroupInfo
168  * @param[in] passphrase Passphrase string, the required length is 0x8-0x3F.
169  */
170 Result lp2pGroupInfoSetPassphrase(Lp2pGroupInfo *info, const char *passphrase);
171 
172 ///@name INetworkService
173 ///@{
174 
175 /**
176  * @brief Scan
177  * @param[in] info \ref Lp2pGroupInfo
178  * @param[out] results Output array of \ref Lp2pScanResult.
179  * @param[in] count Size of the results array in entries.
180  * @param[out] total_out Total output entries.
181  */
182 Result lp2pScan(const Lp2pGroupInfo *info, Lp2pScanResult *results, s32 count, s32 *total_out);
183 
184 /**
185  * @brief CreateGroup
186  * @note The role (\ref lp2pGetRole) must be 0. This eventually sets the role to value 1.
187  * @param[in] info \ref Lp2pGroupInfo
188  */
190 
191 /**
192  * @brief This destroys the previously created group from \ref lp2pCreateGroup.
193  * @note If no group was previously created (role from \ref lp2pGetRole is not 1), this just returns 0.
194  */
196 
197 /**
198  * @brief SetAdvertiseData
199  * @note The role (\ref lp2pGetRole) must be <=1.
200  * @note An empty buffer (buffer=NULL/size=0) can be used to reset the AdvertiseData size in state to zero.
201  * @param[out] buffer Input buffer containing arbitrary user data.
202  * @param[in] size Input buffer size, must be <=0x80.
203  */
204 Result lp2pSetAdvertiseData(const void* buffer, size_t size);
205 
206 /**
207  * @brief This sends an Action frame to the specified \ref Lp2pGroupId, with the specified destination \ref Lp2pMacAddress.
208  * @note The role (\ref lp2pGetRole) must be non-zero.
209  * @note The error from \ref lp2pGetNetworkInterfaceLastError will be returned if it's set.
210  * @note [11.0.0+] Lp2pGroupInfo::security_type must be value 2 (default encryption), otherwise an error is returned.
211  * @param[in] buffer Input buffer containing arbitrary user data.
212  * @param[in] size Input buffer size, must be <=0x400.
213  * @param[in] addr \ref Lp2pMacAddress, this can be a broadcast address. This must be non-zero.
214  * @param[in] group_id \ref Lp2pGroupId
215  * @param[in] frequency Must be >=1. See Lp2pGroupInfo::frequency.
216  * @param[in] channel Must be >=1. See Lp2pGroupInfo::channel.
217  * @param[in] flags Only bit0 is used: clear = block until the data can be sent, set = return error when the data can't be sent.
218  */
219 Result lp2pSendToOtherGroup(const void* buffer, size_t size, Lp2pMacAddress addr, Lp2pGroupId group_id, s16 frequency, s16 channel, u32 flags);
220 
221 /**
222  * @brief This receives an Action frame.
223  * @note The role (\ref lp2pGetRole) must be non-zero.
224  * @note When data is not available, the error from \ref lp2pGetNetworkInterfaceLastError will be returned if it's set.
225  * @param[out] buffer Output buffer containing arbitrary user data.
226  * @param[in] size Output buffer size.
227  * @param[in] flags Only bit0 is used: clear = block until data is available, set = return error when data is not available.
228  * @param[in] addr \ref Lp2pMacAddress
229  * @param[in] unk0 Unknown
230  * @param[in] unk1 Unknown
231  * @param[out] out_size This is the original size used for copying to the output buffer, before it's clamped to the output-buffer size.
232  * @param[out] unk2 Unknown
233  */
234 Result lp2pRecvFromOtherGroup(void* buffer, size_t size, u32 flags, Lp2pMacAddress *addr, u16 *unk0, s32 *unk1, u64 *out_size, s32 *unk2);
235 
236 /**
237  * @brief AddAcceptableGroupId
238  * @param[in] group_id \ref Lp2pGroupId
239  */
241 
242 /**
243  * @brief RemoveAcceptableGroupId
244  */
246 
247 ///@name INetworkServiceMonitor
248 ///@{
249 
250 /**
251  * @brief AttachNetworkInterfaceStateChangeEvent
252  * @note The Event must be closed by the user once finished with it.
253  * @param[out] out_event Output Event with autoclear=false.
254  */
256 
257 /**
258  * @brief GetNetworkInterfaceLastError
259  */
261 
262 /**
263  * @brief GetRole
264  * @param[out] out Output Role.
265  */
267 
268 /**
269  * @brief GetAdvertiseData
270  * @note The role from \ref lp2pGetRole must be value 2.
271  * @param[out] buffer Output buffer data.
272  * @param[in] size Output buffer size.
273  * @param[out] transfer_size Size of the data copied into the buffer.
274  * @param[out] original_size Original size from state.
275  */
276 Result lp2pGetAdvertiseData(void* buffer, size_t size, u16 *transfer_size, u16 *original_size);
277 
278 /**
279  * @brief GetAdvertiseData2
280  * @note This is identical to \ref lp2pGetAdvertiseData except this doesn't run the role validation.
281  * @param[out] buffer Output buffer data.
282  * @param[in] size Output buffer size.
283  * @param[out] transfer_size Size of the data copied into the buffer.
284  * @param[out] original_size Original size from state.
285  */
286 Result lp2pGetAdvertiseData2(void* buffer, size_t size, u16 *transfer_size, u16 *original_size);
287 
288 /**
289  * @brief GetGroupInfo
290  * @note The role from \ref lp2pGetRole must be non-zero.
291  * @param[out] out \ref Lp2pGroupInfo
292  */
294 
295 /**
296  * @brief This runs the same code as \ref lp2pCreateGroup to generate the \ref Lp2pGroupInfo for the input struct.
297  * @param[out] out \ref Lp2pGroupInfo
298  * @param[in] info \ref Lp2pGroupInfo
299  */
301 
302 /**
303  * @brief GetGroupOwner
304  * @note The role from \ref lp2pGetRole must be non-zero.
305  * @param[out] out \ref Lp2pNodeInfo
306  */
308 
309 /**
310  * @brief GetIpConfig
311  * @note The role from \ref lp2pGetRole must be non-zero.
312  * @param[out] out \ref Lp2pIpConfig
313  */
315 
316 /**
317  * @brief Leave
318  * @param[out] out Output value.
319  */
321 
322 /**
323  * @brief AttachJoinEvent
324  * @note The Event must be closed by the user once finished with it.
325  * @param[out] out_event Output Event with autoclear=false.
326  */
328 
329 /**
330  * @brief GetMembers
331  * @note The role from \ref lp2pGetRole must be value 1.
332  * @param[out] members Output array of \ref Lp2pNodeInfo.
333  * @param[in] count Size of the members array in entries. A maximum of 8 entries can be returned.
334  * @param[out] total_out Total output entries.
335  */
336 Result lp2pGetMembers(Lp2pNodeInfo *members, s32 count, s32 *total_out);
337 
338 ///@}
339 
Result lp2pGetMembers(Lp2pNodeInfo *members, s32 count, s32 *total_out)
GetMembers.
Result lp2pLeave(u32 *out)
Leave.
Result lp2pAttachJoinEvent(Event *out_event)
AttachJoinEvent.
Result lp2pScan(const Lp2pGroupInfo *info, Lp2pScanResult *results, s32 count, s32 *total_out)
Scan.
Result lp2pRemoveAcceptableGroupId(void)
RemoveAcceptableGroupId.
Result lp2pGetAdvertiseData2(void *buffer, size_t size, u16 *transfer_size, u16 *original_size)
GetAdvertiseData2.
Result lp2pCreateGroup(const Lp2pGroupInfo *info)
CreateGroup.
static void lp2pGroupInfoSetStealthEnabled(Lp2pGroupInfo *info, bool flag)
Sets Lp2pGroupInfo::stealth_enabled.
Definition: lp2p.h:149
void lp2pCreateGroupInfoScan(Lp2pGroupInfo *info)
Creates a default Lp2pGroupInfo for use with lp2pScan.
Service * lp2pGetServiceSession_INetworkServiceMonitor(void)
Gets the Service object for INetworkServiceMonitor.
Lp2pServiceType
Definition: lp2p.h:14
@ Lp2pServiceType_App
Initializes lp2p:app.
Definition: lp2p.h:15
@ Lp2pServiceType_System
Initializes lp2p:sys.
Definition: lp2p.h:16
Result lp2pAttachNetworkInterfaceStateChangeEvent(Event *out_event)
AttachNetworkInterfaceStateChangeEvent.
static void lp2pGroupInfoSetMemberCountMax(Lp2pGroupInfo *info, size_t count)
Sets Lp2pGroupInfo::member_count_max.
Definition: lp2p.h:129
Result lp2pGroupInfoSetPassphrase(Lp2pGroupInfo *info, const char *passphrase)
Sets the passphrase, for when standard WPA2-PSK is being used.
Result lp2pSetAdvertiseData(const void *buffer, size_t size)
SetAdvertiseData.
void lp2pGroupInfoSetFlags(Lp2pGroupInfo *info, s8 *flags, size_t count)
Sets Lp2pGroupInfo::flags_count and Lp2pGroupInfo::flags.
Result lp2pJoin(Lp2pGroupInfo *out, const Lp2pGroupInfo *info)
This runs the same code as lp2pCreateGroup to generate the Lp2pGroupInfo for the input struct.
void lp2pExit(void)
Exit lp2p.
Result lp2pAddAcceptableGroupId(Lp2pGroupId group_id)
AddAcceptableGroupId.
Result lp2pGetIpConfig(Lp2pIpConfig *out)
GetIpConfig.
Result lp2pRecvFromOtherGroup(void *buffer, size_t size, u32 flags, Lp2pMacAddress *addr, u16 *unk0, s32 *unk1, u64 *out_size, s32 *unk2)
This receives an Action frame.
Result lp2pGetAdvertiseData(void *buffer, size_t size, u16 *transfer_size, u16 *original_size)
GetAdvertiseData.
Result lp2pInitialize(Lp2pServiceType service_type)
Initialize lp2p.
Result lp2pGetNetworkInterfaceLastError(void)
GetNetworkInterfaceLastError.
void lp2pGroupInfoSetServiceName(Lp2pGroupInfo *info, const char *name)
Sets Lp2pGroupInfo::service_name.
void lp2pGroupInfoSetPresharedKey(Lp2pGroupInfo *info, const void *key, size_t size)
Sets the PresharedKey for the specified Lp2pGroupInfo.
static void lp2pGroupInfoSetFrequencyChannel(Lp2pGroupInfo *info, u16 frequency, s16 channel)
Sets Lp2pGroupInfo::frequency and Lp2pGroupInfo::channel.
Definition: lp2p.h:139
Result lp2pGetGroupOwner(Lp2pNodeInfo *out)
GetGroupOwner.
void lp2pCreateGroupInfo(Lp2pGroupInfo *info)
Creates a default Lp2pGroupInfo for use with lp2pCreateGroup / lp2pJoin.
Result lp2pGetGroupInfo(Lp2pGroupInfo *out)
GetGroupInfo.
Result lp2pSendToOtherGroup(const void *buffer, size_t size, Lp2pMacAddress addr, Lp2pGroupId group_id, s16 frequency, s16 channel, u32 flags)
This sends an Action frame to the specified Lp2pGroupId, with the specified destination Lp2pMacAddres...
Result lp2pDestroyGroup(void)
This destroys the previously created group from lp2pCreateGroup.
Result lp2pGetRole(u8 *out)
GetRole.
Service * lp2pGetServiceSession_INetworkService(void)
Gets the Service object for INetworkService.
Kernel-mode event structure.
Definition: event.h:13
GroupId.
Definition: lp2p.h:25
GroupInfo lp2pScan only uses the following fields for the cmd input struct: supported_platform/priori...
Definition: lp2p.h:31
u8 supported_platform
SupportedPlatform. Must match value 1. 0 is PlatformIdNX, 1 is PlatformIdFuji.
Definition: lp2p.h:38
s16 channel
Wifi channel number. 0 = use default, otherwise this must be one of the following depending on the fr...
Definition: lp2p.h:43
s8 flags_count
Must be <=0x3F.
Definition: lp2p.h:36
u8 stealth_enabled
StealthEnabled. Bool flag, controls whether the SSID is hidden.
Definition: lp2p.h:50
u8 unk_x8C
Unknown.
Definition: lp2p.h:48
u8 unk_x83
Unknown.
Definition: lp2p.h:41
u8 priority
Priority. Must match one of the following, depending on the used service (doesn't apply to lp2pJoin):...
Definition: lp2p.h:49
u8 network_mode
NetworkMode.
Definition: lp2p.h:44
u8 unk_x8F
If zero, a default value of 0x20 is used.
Definition: lp2p.h:51
s8 static_aes_key_index
StaticAesKeyIndex. Used as the array-index for selecting the KeySource used with GenerateAesKek durin...
Definition: lp2p.h:47
u8 performance_requirement
PerformanceRequirement.
Definition: lp2p.h:45
Lp2pGroupId group_id
Should be all-zero for the input struct so that the default is used.
Definition: lp2p.h:34
u16 frequency
Wifi frequency: 24 = 2.4GHz, 50 = 5GHz.
Definition: lp2p.h:42
s8 member_count_max
MemberCountMax. Must be <=0x8. If zero during group-creation, a default of value 1 is used for the va...
Definition: lp2p.h:39
u8 security_type
Security type, used during key derivation. 0 = use defaults, 1 = plaintext, 2 = encrypted....
Definition: lp2p.h:46
u8 preshared_key_binary_size
PresharedKeyBinarySize.
Definition: lp2p.h:53
u8 unk_x82
Unknown.
Definition: lp2p.h:40
u64 local_communication_id
LocalCommunicationId. When zero, the value from the user-process control.nacp is loaded....
Definition: lp2p.h:33
IpConfig. Only contains IPv4 addresses.
Definition: lp2p.h:76
MacAddress.
Definition: lp2p.h:20
NodeInfo.
Definition: lp2p.h:68
Lp2pMacAddress mac_addr
Lp2pMacAddress
Definition: lp2p.h:71
ScanResult.
Definition: lp2p.h:58
u16 advertise_data_size
Size of the following AdvertiseData.
Definition: lp2p.h:62
u8 unk_x200
Unknown.
Definition: lp2p.h:60
Lp2pGroupInfo group_info
Lp2pGroupInfo
Definition: lp2p.h:59
Service object structure.
Definition: service.h:14
uint64_t u64
64-bit unsigned integer.
Definition: types.h:22
uint8_t u8
8-bit unsigned integer.
Definition: types.h:19
int8_t s8
8-bit signed integer.
Definition: types.h:25
int16_t s16
16-bit signed integer.
Definition: types.h:26
uint16_t u16
16-bit unsigned integer.
Definition: types.h:20
u32 Result
Function error code result type.
Definition: types.h:44
#define NX_CONSTEXPR
Flags a function as constexpr in C++14 and above; or as (always) inline otherwise.
Definition: types.h:92
int32_t s32
32-bit signed integer.
Definition: types.h:27
uint32_t u32
32-bit unsigned integer.
Definition: types.h:21