LDN services: Difference between revisions

 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
LDN handles all local network communication.
LDN handles all local network communication.
There's 2 IPC handler threads for all ldn:* services.


= ldn:m =
= ldn:m =
Line 45: Line 47:


=== GetState ===
=== GetState ===
No input, returns an output u32.
No input, returns an output [[#State|u32]].


sdknso implements this by <code>return</code>ing the u32, with 0 being returned on error.
sdknso implements this by <code>return</code>ing the u32, with 0 being returned on error.
Line 88: Line 90:
= ldn:s =
= ldn:s =
This is "nn::ldn::detail::ISystemServiceCreator".
This is "nn::ldn::detail::ISystemServiceCreator".
This has IPC max_sessions 5.


[18.0.0+] The sdknso uses SessionManager with this, where the additional session-count is 0x3.
[18.0.0+] The sdknso uses SessionManager with this, where the additional session-count is 0x3.
Line 203: Line 207:
=== GetNetworkInfo ===
=== GetNetworkInfo ===
Takes a type-0x1A output buffer containing a [[#NetworkInfo]].
Takes a type-0x1A output buffer containing a [[#NetworkInfo]].
[[#GetState|State]] must be 3 or 5.


=== GetIpv4Address ===
=== GetIpv4Address ===
Line 379: Line 385:
This is used immediately after object creation.
This is used immediately after object creation.


With [7.0.0+] [[#InitializeWithVersion|InitializeWithVersion]] is used instead. The cmd impl for Initialize uses [[#InitializeWithVersion|InitializeWithVersion]] with input_u32=0.
On old sysvers the cmd impl for User/System are identical, except different params are used for the funcs called internally.
 
With [7.0.0+] [[#InitializeWithVersion|InitializeWithVersion]] is used instead. The cmd impl for Initialize uses [[#InitializeWithVersion|InitializeWithVersion]] with version=0.


=== Finalize ===
=== Finalize ===
Line 398: Line 406:


=== InitializeWithVersion ===
=== InitializeWithVersion ===
Takes an input PID, an u32, and an u64 pid_placeholder.
Takes an input PID, a s32 version, and an u64 pid_placeholder.


Official sw uses hard-coded value 0x1 for the u32.
The priority is determined by whether the interface is User/System: System = 0x38, User = 0x5A.


The input u32 is ignored, the impl for this cmd is identical to [[#Initialize_2|Initialize]].
It then calls the init func, with the cmd input params and the above priority, returning the Result on failure.


Internally this calls a func with params: (..., PID, &{u16 value 0x38}). On success, this then calls another func (which sets two state fields to the input) with params: (state, 0) (these state fields are used during [[#Authentication]] to check which service is being used).
On newer sysvers this then adds an entry for the state array used by [[#RegisterClient|RegisterClient]].


The first func uses various [[Network_Interface_services|nifm]] funcs. The input value is used to determine the value for [[Network_Interface_services#CreateRequest|nn::nifm::RequestParameters]]: essentially, value 0x4 is used for ldn:u, and value 0x8 is used for ldn:s. The input value is also copied into state.
Lastly the input PID and version are written into state, then this returns.


[[#GetState|State]] must be 0, this cmd eventually sets the State to value 1.
The init func does the following:
* The PID must be non-zero, and the version must not be negative. The priority must be 0x5A or 0x38.
* An error is returned if state fields are invalid.
* The input PID and version are written into state (a state field is also set to interface == User).
* Lastly, a vfunc is called with the input priority, returning the Result from that.
 
The vfunc does the following:
* On newer sysvers, this uses [[Shared_Database_services|pl:s]] RequestApplicationFunctionAuthorizationByProcessId with the input PID and [[Shared_Database_services|ApplicationFunctionAuthorizationId]] = 2 (SecureLdnLocalCommunication), returning the Result on failure.
* Then a message is sent to a msg-queue with the input priority.
 
The handler for the above message does the following:
* When state is already initialized, runs handling for that. An error is also thrown if the input priority is larger than a state field.
* Initializes state, etc.
* Various [[Network_Interface_services|nifm]] funcs are eventually used. The input priority is used to determine the value for [[Network_Interface_services#CreateRequest|nn::nifm::RequestParameters]]: value 0x4 or value 0x8 is used, depending on priority > 0x59.
** Newer versions also handle ldn lan_emulation [[System_Settings|sys-settings]] here. For the above value, when lan_emulation is enabled it uses value 0x17, with 0x18 additionally used for priority <= 0x59.
* The rest is state init, including setting [[#State|State]] to value 1. Then 0 is returned.
 
On old sysvers the cmd impl for User/System are identical, except different params are used for the funcs called internally. With newer sysvers the cmd impl is now identical.
 
Version values passed by official sw:
 
{| class="wikitable" border="1"
|-
! Value || SystemVersion
|-
| 0x1 || [7.0.0+]
|-
| 0x2 || [18.0.0+]
|-
| 0x3 || [19.0.0+]
|-
| 0x4 || [20.0.0+]
|}


=== InitializeWithPriority ===
=== InitializeWithPriority ===
Takes an input PID, an u32, an u32, and an u64 pid_placeholder.
Takes an input PID, a s32 version, a s32 priority, and an u64 pid_placeholder.


This is similar to [[#InitializeWithVersion|InitializeWithVersion]], with the additional cmd input u32 now being passed directly to the init func which is called here.
This is similar to [[#InitializeWithVersion|InitializeWithVersion]]. The input priority is passed directly to the init func which is called here, instead of determining it from whether the interface is User/System.
 
Official sw passes input value 0x38 for the priority as the default, when the user doesn't specify the priority.


=== EnableActionFrame ===
=== EnableActionFrame ===
Line 434: Line 476:
The ChannelNumber must be non-zero.
The ChannelNumber must be non-zero.


[[#State|State]] must be 3-4 (AccessPointCreated/Station).
[[#State|State]] must be 3-5 (AccessPointCreated/Station/StationConnected).


=== RecvActionFrame ===
=== RecvActionFrame ===
Line 495: Line 537:
= ldn:u =
= ldn:u =
This is "nn::ldn::detail::IUserServiceCreator".
This is "nn::ldn::detail::IUserServiceCreator".
This has IPC max_sessions 3.


[18.0.0+] The sdknso uses SessionManager with this, where the additional session-count is 0x3.
[18.0.0+] The sdknso uses SessionManager with this, where the additional session-count is 0x3.
Line 514: Line 558:
== IUserLocalCommunicationService ==
== IUserLocalCommunicationService ==
This is "nn::ldn::detail::IUserLocalCommunicationService".
This is "nn::ldn::detail::IUserLocalCommunicationService".
This is identical to [[#ISystemLocalCommunicationService]], except for the System-only cmd(s), and [[#Initialize_3|Initialize]]/[[#InitializeWithVersion_2|InitializeWithVersion]] differ.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 577: Line 619:
| 304 || [[#Disconnect|Disconnect]]
| 304 || [[#Disconnect|Disconnect]]
|-
|-
| 400 || [[#Initialize_3|Initialize]]
| 400 || [[#Initialize_2|Initialize]]
|-
|-
| 401 || [[#Finalize_3|Finalize]]
| 401 || [[#Finalize_2|Finalize]]
|-
|-
| 402 || [7.0.0+] [[#InitializeWithVersion_2|InitializeWithVersion]]
| 402 || [7.0.0+] [[#InitializeWithVersion|InitializeWithVersion]]
|-
|-
| 403 || [19.0.0+] [[#InitializeWithPriority|InitializeWithPriority]]
| 403 || [19.0.0+] [[#SetOperationMode|SetOperationMode]]
|-
|-
| 500 || [18.0.0+] [[#EnableActionFrame|EnableActionFrame]]
| 500 || [18.0.0+] [[#EnableActionFrame|EnableActionFrame]]
Line 599: Line 641:
| 601 || [18.0.0+] [[#ResetTxPower|ResetTxPower]]
| 601 || [18.0.0+] [[#ResetTxPower|ResetTxPower]]
|}
|}
=== Initialize ===
Takes an input PID and an u64 pid_placeholder.
This is used immediately after object creation.
With [7.0.0+] [[#InitializeWithVersion_2|InitializeWithVersion]] is used instead.
This is identical to [[#Initialize_2|Initialize]] except different params are used for the funcs called internally.
=== Finalize ===
No input/output.
This is used during service exit, prior to closing the object. Official sw will Abort if this fails.
=== InitializeWithVersion ===
Takes an input PID, an u32, and an u64 pid_placeholder.
Official sw uses hard-coded value 0x1 for the u32.
The input u32 is ignored, the impl for this cmd is identical to [[#Initialize_3|Initialize]].
This is identical to [[#InitializeWithVersion|InitializeWithVersion]] except different params are used for the funcs called internally: the u16 value is 0x5A, and the value for the second func is 1.


= ndd =
= ndd =
Line 1,334: Line 1,353:
= UserConfig =
= UserConfig =
This is "nn::ldn::UserConfig". This is a 0x30-byte struct with 1-byte alignment.
This is "nn::ldn::UserConfig". This is a 0x30-byte struct with 1-byte alignment.
An error is thrown if UserName+0x20 is non-zero.


sdknso copies the input UserConfig to a tmp struct on stack, which is then used with the cmd. Only the first 0x20-bytes are copied, with the rest cleared.
sdknso copies the input UserConfig to a tmp struct on stack, which is then used with the cmd. Only the first 0x20-bytes are copied, with the rest cleared.
Line 1,453: Line 1,474:
* Local-game-update with a S2-only Application.
* Local-game-update with a S2-only Application.
* Local-game-update for a S1-game which has a Nintendo Switch 2 Edition available, even without the S2-Edition being installed.
* Local-game-update for a S1-game which has a Nintendo Switch 2 Edition available, even without the S2-Edition being installed.
There's system-titles which [[20.0.0|use]] SetProtocol. While there's game(s) which use SetProtocol, there's no known (?) games using Protocol3 (excluding GameShare which is system).


= ActionFrameSettings =
= ActionFrameSettings =
Line 1,641: Line 1,664:
After Authentication the Station will scan for another [[#ActionFrame]], with frame-comparision enabled with the above frame (frame must have been updated since the previous scan). The Station locates the index for a [[#MacAddress|MacAddress]] matching itself in the [[#NetworkInfo]] [[#NodeInfo|NodeInfo]] array (the entry for the AccessPoint is skipped), throwing an error if not found. After validating the LocalCommunicationVersion, it proceeds to handle ARP setup below.
After Authentication the Station will scan for another [[#ActionFrame]], with frame-comparision enabled with the above frame (frame must have been updated since the previous scan). The Station locates the index for a [[#MacAddress|MacAddress]] matching itself in the [[#NetworkInfo]] [[#NodeInfo|NodeInfo]] array (the entry for the AccessPoint is skipped), throwing an error if not found. After validating the LocalCommunicationVersion, it proceeds to handle ARP setup below.


This does not use DHCP, each node on the network has to manually setup ARP (without sending ARP network requests) with the [[#NodeInfo|NodeInfo]] array in [[#NetworkInfo]]. [?+] After the client is [[#EthFrame|authenticated]] the host sends an ARP reply to the client (there's no ARP usage besides this).
This does not use DHCP, each node on the network has to manually setup IP-config with the [[#NodeInfo|NodeInfo]] array in [[#NetworkInfo]]. [?+] After the client is [[#EthFrame|authenticated]] ARP may be used in some cases however.


At this point standard sockets can be used over Data frames.
At this point standard sockets can be used over Data frames.