Changes

Jump to navigation Jump to search
7,628 bytes added ,  17:21, 3 December 2020
Line 573: Line 573:  
These were added with [9.0.0+].
 
These were added with [9.0.0+].
   −
lp2p:app is used by [[Mario Kart Live: Home Circuit]].
+
lp2p:app is used by [[Mario Kart Live: Home Circuit]]. lp2p:sys is used by [[Album_Applet|LibraryAppletPhotoViewer]] with [11.0.0+].
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 644: Line 644:     
=== Scan ===
 
=== Scan ===
Takes a type-0x19 input buffer containing a 0x200-byte struct, a type-0x22 output buffer containing an array of [[#ScanResult]], returns an output s32 total_out.
+
Takes a type-0x19 input buffer containing a [[#GroupInfo]], a type-0x22 output buffer containing an array of [[#ScanResult]], returns an output s32 total_out.
    
=== CreateGroup ===
 
=== CreateGroup ===
Takes a type-0x31 input buffer containing a 0x200-byte struct, no output.
+
Takes a type-0x31 input buffer containing a [[#GroupInfo]], no output.
    
[[Mario Kart Live: Home Circuit|mklive]] uses the following string with this: "Failed to create a group: %08X".
 
[[Mario Kart Live: Home Circuit|mklive]] uses the following string with this: "Failed to create a group: %08X".
   −
This is only available if a group wasn't already created.
+
The [[#GetRole|role]] must be 0. This eventually sets the [[#GetRole|role]] to value 1.
    
=== DestroyGroup ===
 
=== DestroyGroup ===
 
No input/output.
 
No input/output.
   −
This destroys the previously [[#CreateGroup|created]] group. If no group was previously created, this just returns 0.
+
This destroys the previously [[#CreateGroup|created]] group. If no group was previously created ([[#GetRole|role]] is not 1), this just returns 0.
    
=== SetAdvertiseData ===
 
=== SetAdvertiseData ===
 
Takes a type-0x21 input buffer, no output.
 
Takes a type-0x21 input buffer, no output.
   −
The buffer size must be <=0x80.
+
The buffer size must be <=0x80. The [[#GetRole|role]] must be <=1.
    
A string in [[Mario Kart Live: Home Circuit|mklive]] refers to the buffer data as "scan advertise data".
 
A string in [[Mario Kart Live: Home Circuit|mklive]] refers to the buffer data as "scan advertise data".
Line 670: Line 670:  
The buffer size must be <=0x400.
 
The buffer size must be <=0x400.
   −
The s16s must be >=1.
+
The MacAddress must be non-zero. The s16s must be >=1.
   −
Flags is only used for selecting which func to call internally, via bit0.
+
Only bit0 is used from flags: clear = block until the data can be sent, set = return error when the data can't be sent.
    
A string in [[Mario Kart Live: Home Circuit|mklive]] refers to the buffer data as "Action frame".
 
A string in [[Mario Kart Live: Home Circuit|mklive]] refers to the buffer data as "Action frame".
   −
This is only available when a group was previously [[#CreateGroup|created]].
+
The [[#GetRole|role]] must be non-zero. The error from [[#GetNetworkInterfaceLastError]] will be returned if it's set.
 +
 
 +
[11.0.0+] [[#GroupInfo]]+0x8A must be value 2, otherwise an error is returned.
    
This sends an Action frame to the specified [[#GroupId]], with the specified destination [[#MacAddress_2|MacAddress]] (can be a broadcast address).
 
This sends an Action frame to the specified [[#GroupId]], with the specified destination [[#MacAddress_2|MacAddress]] (can be a broadcast address).
Line 687: Line 689:  
The out_size is the original size used for copying to the output buffer, before it's clamped to the output-buffer size.
 
The out_size is the original size used for copying to the output buffer, before it's clamped to the output-buffer size.
   −
Flags is only used for selecting which func to call internally, via bit0.
+
Only bit0 is used from flags: clear = block until data is available, set = return error when data is not available.
   −
This is only available when a group was previously [[#CreateGroup|created]].
+
When data is not available, the error from [[#GetNetworkInterfaceLastError]] will be returned if it's set.
   −
This receives an Action frame. This will block until data is available (?).
+
The [[#GetRole|role]] must be non-zero.
 +
 
 +
This receives an Action frame.
    
=== AddAcceptableGroupId ===
 
=== AddAcceptableGroupId ===
Line 752: Line 756:  
Takes a type-0x22 output buffer, returns 2 output u16s.
 
Takes a type-0x22 output buffer, returns 2 output u16s.
   −
Validates that the [[#GetRole|role]] is value 0x2, then copies data from state into the output buffer. The first output u16 is the size used for the memcpy, the second u16 is the original size from state.
+
Validates that the [[#GetRole|role]] is value 2, then copies data from state into the output buffer. The first output u16 is the size used for the memcpy, the second u16 is the original size from state.
    
=== GetAdvertiseData2 ===
 
=== GetAdvertiseData2 ===
Line 765: Line 769:     
=== Join ===
 
=== Join ===
Takes a type-0x32 output buffer containing a [[#GroupInfo]] and a type-0x31 input buffer containing a 0x200-byte struct.
+
Takes a type-0x32 output buffer containing a [[#GroupInfo]] and a type-0x31 input buffer containing a [[#GroupInfo]].
    
This runs the same code as [[#CreateGroup]] to generate the [[#GroupInfo]] for the input struct (which with [[#CreateGroup]] would be available with [[#GetGroupInfo]]). The input struct is the same as [[#CreateGroup]].
 
This runs the same code as [[#CreateGroup]] to generate the [[#GroupInfo]] for the input struct (which with [[#CreateGroup]] would be available with [[#GetGroupInfo]]). The input struct is the same as [[#CreateGroup]].
Line 779: Line 783:  
Validates that the [[#GetRole|role]] is non-zero, then copies the struct from state into the output buffer.
 
Validates that the [[#GetRole|role]] is non-zero, then copies the struct from state into the output buffer.
   −
u32 +0x24 is the network-endian Ipv4 address, u32 +0x44 is the network-endian subnet-mask.
+
+0x20 is the <code>struct sockaddr</code> IP address, +0x40 is the <code>struct sockaddr</code> subnet-mask, +0x60 is the <code>struct sockaddr</code> gateway(?). The address for the last one is set to localhost.
    
=== Leave ===
 
=== Leave ===
Line 790: Line 794:  
Takes a type-0x22 output buffer containing an array of [[#NodeInfo_2|NodeInfo]], returns an output s32 total_out.
 
Takes a type-0x22 output buffer containing an array of [[#NodeInfo_2|NodeInfo]], returns an output s32 total_out.
   −
Validates that the [[#GetRole|role]] is value 0x1. Then any entries from state which are available are copied into the output array buffer, if there's space available.
+
Validates that the [[#GetRole|role]] is value 1. Then any entries from state which are available are copied into the output array buffer, if there's space available. A maximum of 8 entries can be returned.
    
A string in [[Mario Kart Live: Home Circuit|mklive]] refers to the array data as "connected members".
 
A string in [[Mario Kart Live: Home Circuit|mklive]] refers to the array data as "connected members".
Line 1,185: Line 1,189:  
! Description
 
! Description
 
|-
 
|-
| 0x0 || 0x4 || [[#Ipv4Address]]
+
| 0x0 || || <code>struct sockaddr</code> for the IP address.
 
|-
 
|-
| 0x4 || 0x6 || [[#MacAddress_2|MacAddress]]
+
| 0x24 || 0x6 || [[#MacAddress_2|MacAddress]]
 
|}
 
|}
    
= GroupInfo =
 
= GroupInfo =
 
This is "nn::lp2p::GroupInfo". This is a 0x200-byte struct.
 
This is "nn::lp2p::GroupInfo". This is a 0x200-byte struct.
 +
 +
[[Mario Kart Live: Home Circuit|mklive]] sets the SSID to a string generated from random data.
 +
 +
[[#Scan_2|Scan]] only uses the following fields for the cmd input struct: SupportedPlatform/Priority, Frequency/Channel, and PresharedKeyBinarySize/PresharedKey.
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 1,199: Line 1,207:  
! Description
 
! Description
 
|-
 
|-
| 0x10 || 0x8 || LocalCommunicationId
+
| 0x0 || 0x10 || When zero, this is set to randomly-generated data. Used during key derivation.
 +
|-
 +
| 0x10 || 0x8 || LocalCommunicationId. When zero, the value from control.nacp is loaded. This is later validated by [[#Join]]/[[#CreateGroup]] the same way as the [[#NetworkConfig]] field. Used during key derivation.
 +
|-
 +
| 0x18 || 0x6 || [[#GroupId]] ("GROUP ID  (BSSID)"). When zero, the default is used. The default should be used here: an error is thrown if the data here doesn't match the output from [[WLAN_services|wlan:lcl]] cmd2.
 +
|-
 +
| 0x1E || 0x21 || ServiceName ("GROUP NAME (SSID)"). NUL-terminated string. If the SSID is invalid, a new SSID is generated, however in this case the original SSID must contain a '-' character.
 +
|-
 +
| 0x3F || 0x1 || s8 Flags count. Must be <=0x3F.
 +
|-
 +
| 0x40 || 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. global_flags are also masked with flags loaded from here. User-processes use entryval=1 as the default, with [11.0.0+] entryval=0 can be used for standard WPA2-PSK (see +0x8A).
 
|-
 
|-
| 0x18 || 0x6 || "GROUP ID  (BSSID)" [[#GroupId]]
+
| 0x80 || 0x1 || SupportedPlatform. Must match value 1. 0 is PlatformIdNX, 1 is PlatformIdFuji.
 
|-
 
|-
| 0x1E || 0x21 || "GROUP NAME (SSID)" NUL-terminated string.
+
| 0x81 || 0x1 || MemberCountMax. s8, Must be <=0x8. During group creation this is passed to [[WLAN_services|wlan:lcl]] cmd40, when this is value 0 a default of value 1 is passed. During group-creation when the below +0x88 field is not value 0x2, the passed [[BTM_services#SetWlanMode|WlanMode]] is <code>x81_field_val > 3</code>.
 
|-
 
|-
| 0x84 || 0x2 || Wifi frequency: 24 = 2.4GHz, 50 = 5.0GHz.
+
| 0x82 || 0x1 ||  
 
|-
 
|-
| 0x86 || 0x2 || "CHANNEL" s16. 0 = use default, otherwise this must be one of the following depending on the frequency field:
+
| 0x84 || 0x2 || Frequency. Wifi frequency: 24 = 2.4GHz, 50 = 5GHz.
 +
|-
 +
| 0x86 || 0x2 || s16 Channel ("CHANNEL"). Wifi channel number. 0 = use default, otherwise this must be one of the following depending on the frequency field:
 
* 24: 1, 6, 11.
 
* 24: 1, 6, 11.
 
* 50: 36, 40, 44, 48.
 
* 50: 36, 40, 44, 48.
 +
|-
 +
| 0x88 || 0x1 || NetworkMode. Used during group-creation to determine the [[BTM_services#SetWlanMode|WlanMode]] to use. When this is value 0x2, mode=3 is used, otherwise it's determined via the +0x81 field.
 +
|-
 +
| 0x89 || 0x1 || PerformanceRequirement.
 +
|-
 +
| 0x8A || 0x1 || Security type, used during key derivation. 0 = use defaults, 1 = plaintext, 2 = encrypted. [11.0.0+] 3: Standard WPA2-PSK.
 +
|-
 +
| 0x8B || 0x1 || StaticAesKeyIndex. s8, used as the array-index for selecting the KeySource used with [[SPL_services#GenerateAesKek|GenerateAesKek]] during key derivation. Should be 1-2, otherwise GenerateAesKek is skipped and zeros are used for the AccessKey instead.
 +
|-
 +
| 0x8D || 0x1 || Priority. Must match one of the following, depending on the used service (doesn't apply to [[#Join]]): 55 = SystemPriority (lp2p:sys), 90 = ApplicationPriority (lp2p:app and lp2p:sys).
 +
|-
 +
| 0x8E || 0x1 || StealthEnabled. Bool flag, controls whether the SSID is hidden.
 +
|-
 +
| 0x8F || 0x1 || If zero, a default value of 0x20 is used.
 +
|-
 +
| 0x1C0 || 0x1 || PresharedKeyBinarySize. Must be 0x20 for PresharedKeyBinary. [11.0.0+] With WPA2-PSK, this must be value 1.
 +
|-
 +
| 0x1C1 || 0x3F ([9.0.0-10.2.0] 0x20) || PresharedKey. Used during key derivation. [11.0.0+] With WPA2-PSK, this is the passphrase string.
 
|}
 
|}
 +
 +
loaded_flags are first loaded from elsewhere, then masked with the above flags when available. loaded_flags are used when +0x8A is 0. global_flags are loaded from global data. These flags are only used with [[#CreateGroup]]/[[#Join]]. Flags (note that the following was updated with [11.0.0+], and differs from below):
 +
* Bit2 clear:
 +
** global_flags must be non-zero, and loaded_flags bit1 must be set.
 +
** u8 +0x8A is set to value 1.
 +
** When the cached [[SPL_services#IsDevelopment|IsDevelopment]] value is false (retail), an error is thrown.
 +
** u8 +0x8B is set to value 0.
 +
* Otherwise, if bit2 is set:
 +
** u8 +0x8A is set to value 2.
 +
** global_flags bit1 set:
 +
*** u8 +0x8B is set to value 1.
 +
** Otherwise, if global_flags bit2 is set:
 +
*** u8 +0x8B is set to value 2.
    
= ScanResult =
 
= ScanResult =
Line 1,221: Line 1,272:  
! Description
 
! Description
 
|-
 
|-
| 0x18 || 0x6 || [[#MacAddress_2|MacAddress]]?
+
| 0x0 || 0x200 || [[#GroupInfo]]
|-
  −
| 0x86 || 0x1 ||
   
|-
 
|-
 
| 0x200 || 0x1 ||  
 
| 0x200 || 0x1 ||  
 
|-
 
|-
| 0x206 || 0x2 || Size of the following data.
+
| 0x206 || 0x2 || AdvertiseData size.
 
|-
 
|-
| 0x208 || 0x80 || Data with the size specified above. Advertise data?
+
| 0x208 || 0x80 || AdvertiseData
 
|}
 
|}
   Line 1,454: Line 1,503:     
== lp2p ==
 
== lp2p ==
This is used for communicating with accessories over local wifi - in particular, [[Mario Kart Live: Home Circuit]] uses this.
+
This is used for communicating with accessories (external devices on [11.0.0+]) over local wifi. [[Mario Kart Live: Home Circuit]] uses this. [11.0.0+] [[Album_Applet|LibraryAppletPhotoViewer]] uses this.
   −
A beacon is broadcasted. The SSID in the beacon is hidden (all-zero with the same length as the original SSID). The beacon contains two custom Nintendo tags with OUI <code>00:22:aa</code>. The beacon is identical to ldn, except for the following (besides SSID length difference and the lp2p-only Nintendo tags):  
+
A beacon is broadcasted.
 +
 
 +
Action frames are only sent when done so by [[#SendToOtherGroup]] (other than the Epigram one mentioned below).
 +
 
 +
Communication uses sockets with standard Data frames and the above Action frames. Switch consoles presumably only use the Action frames to communicate with each other?
 +
 
 +
The key derived by ldn-sysmodule is used directly as the static CCMP key for all data-frames (CCMP / MIC is standard). However, with [[#GroupInfo]]+0x8A value 3, standard WPA2-PSK is used instead.
 +
 
 +
This uses infrastructure-mode (AccessPoint), and DHCP is used. The group-owner is the AccessPoint. Note that the probe response includes the same Nintendo tags included with the beacon. Once connected, the group-owner sends the same Epigram-vendor Action frame(s) described in [[#ldn]]. At this point socket communication can begin, including DHCP usage.
 +
 
 +
The DHCP server thread is started by the "nn.lp2p.StateMachine" thread eventually during group [[#CreateGroup|creation]]. The DHCP Offer option values are the following:
 +
* "Subnet Mask: 255.255.255.0"
 +
* "DHCP Server Identifier: {...}"
 +
* "Broadcast Address: {...}"
 +
* "IP Address Lease Time: (5s) 5 seconds"
 +
* "Renewal Time Value: (0s) 0 seconds"
 +
* "Rebinding Time Value: (0s) 0 seconds"
 +
* "Interface MTU: 1500"
 +
 
 +
Note that the above options doesn't include "Domain Name Server" or "Router", the client device may fail to connect if it doesn't allow those DHCP options to be missing.
 +
 
 +
=== Beacon ===
 +
The SSID in the beacon can optionally be [[#GroupInfo|hidden]] (all-zero with the same length as the original SSID). The beacon contains two custom Nintendo tags with OUI <code>00:22:aa</code>. These Nintendo tags are not used when standard WPA2-PSK is being used. The beacon is identical to ldn, except for the following (besides SSID length difference and the lp2p-only Nintendo tags):  
 
* "Tag: Traffic Indication Map (TIM)": "DTIM count" for lp2p is 1, with ldn it's 0.
 
* "Tag: Traffic Indication Map (TIM)": "DTIM count" for lp2p is 1, with ldn it's 0.
 
* "Tag: HT Capabilities (802.11n D1.10)": "HT Short GI for 20MHz" is set to "Not supported", for ldn it's "Supported".
 
* "Tag: HT Capabilities (802.11n D1.10)": "HT Short GI for 20MHz" is set to "Not supported", for ldn it's "Supported".
 
* "Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element" "Ac Parameters ACI 0": "CW Min: 15" for lp2p, "CW Min: 63" for ldn.
 
* "Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element" "Ac Parameters ACI 0": "CW Min: 15" for lp2p, "CW Min: 63" for ldn.
   −
Action frames are only sent when done so by [[#SendToOtherGroup]].
+
Note that during group creation the beacon may be missing the Nintendo tags in some cases, since group creation didn't finish yet.
   −
Communication uses standard sockets and the above Action frames. Switch consoles presumably only use the Action frames to communicate with each other?
+
The first Nintendo tag contains the following data:
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || 0x2 || Usually 06 00?
 +
|-
 +
| 0x2 || 0x2 || Usually 20 02?(Second byte depends on whether encryption is used?)
 +
|-
 +
| 0x4 || 0x2 || Usually 01 00 or 02 00?(varies)
 +
|-
 +
| 0x6 || 0x8 || Big-endian version of [[#GroupInfo]]+0x10.
 +
|-
 +
| 0xE || 0x10 || Same as [[#GroupInfo]]+0x0.
 +
|-
 +
| 0x1E || || Start of encrypted (and crypto-related) data if enabled. 0x22-bytes when encrypted, 0xE-bytes when plaintext.
 +
|}
   −
It's unknown how connecting (?) to the group owner is done - there's no response to probe requests sent by a Linux machine.
+
The second Nintendo tag contains the following data (data starting at +0x2 is encrypted if enabled, there's also an additional 0x14-bytes when encrypted):
   −
The DHCP server thread is started by the "nn.lp2p.StateMachine" thread eventually during group [[#CreateGroup|creation]].
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || 0x2 || Usually 06 01?
 +
|-
 +
| 0x2 || 0x1 || Plaintext: usually 21?
 +
|-
 +
| 0x3 || 0x1 || Plaintext: AdvertiseData size
 +
|-
 +
| 0x4 || {above size} || Plaintext: AdvertiseData
 +
|}
 +
 
 +
=== ActionFrame ===
 +
The Action frames have the following structure:
 +
* "Fixed parameters":
 +
** "Category code: Vendor Specific (127)"
 +
** "OUI: 00:22:aa (Nintendo Co., Ltd.)"
 +
* The Data starts with the following:
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || 0x2 || Usually 06 00?
 +
|-
 +
| 0x2 || 0x2 || Usually 20 02?(Second byte depends on whether encryption is used?)
 +
|-
 +
| 0x4 || 0x2 || Usually 02 00?(varies)
 +
|-
 +
| 0x6 || 0x8 || Big-endian version of [[#GroupInfo]]+0x10.
 +
|-
 +
| 0xE || 0x10 || Same as [[#GroupInfo]]+0x0.
 +
|}
 +
 
 +
When encryption is used, the remaining data is:
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || 0x4 || Big-endian u32 Counter. The initial value is randomly-generated (?). This is incremented with each sent Action frame.
 +
|-
 +
| 0x4 || {remaining size} || Encrypted user-data. Also includes 0x10-bytes of unknown data.
 +
|}
 +
 
 +
When plaintext is used, the remaining data is:
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0 || {remaining size} || Plaintext user-data.
 +
|}
    
[[Category:Services]]
 
[[Category:Services]]

Navigation menu