LDN handles all local network communication.

ldn:m

This is "nn::ldn::detail::IMonitorServiceCreator".

Cmd Name
0 #CreateMonitorService

CreateMonitorService

Returns an #IMonitorService.

The user-process closes the IMonitorServiceCreator object immediately after using this cmd.

IMonitorService

This is "nn::ldn::detail::IMonitorService".

Cmd Name
0 #GetStateForMonitor
1 #GetNetworkInfoForMonitor
2 #GetIpv4AddressForMonitor
3 #GetDisconnectReasonForMonitor
4 #GetSecurityParameterForMonitor
5 #GetNetworkConfigForMonitor
100 #InitializeMonitor
101 #FinalizeMonitor

GetStateForMonitor

No input, returns an output u32.

sdknso implements this by returning the u32, with 0 being returned on error.

GetNetworkInfoForMonitor

Takes a type-0x1A output buffer containing a #NetworkInfo.

GetIpv4AddressForMonitor

No input, returns an output #Ipv4Address and a #SubnetMask.

GetDisconnectReasonForMonitor

No input, returns an output s16.

This is not exposed by sdknso.

This just returns 0.

GetSecurityParameterForMonitor

No input, returns an output #SecurityParameter.

This is not exposed by sdknso.

GetNetworkConfigForMonitor

No input, returns an output #NetworkConfig.

This is not exposed by sdknso.

InitializeMonitor

No input/output.

This is used immediately after object creation. Official sw will Abort if this fails.

This just returns 0.

FinalizeMonitor

No input/output.

This is used during service exit, prior to closing the object. Official sw will Abort if this fails.

This just returns 0.

ldn:s

This is "nn::ldn::detail::ISystemServiceCreator".

Cmd Name
0 #CreateSystemLocalCommunicationService

CreateSystemLocalCommunicationService

Returns an #ISystemLocalCommunicationService.

The user-process closes the ISystemServiceCreator object immediately after using this cmd. Official sw ignores errors from this cmd.

ISystemLocalCommunicationService

This is "nn::ldn::detail::ISystemLocalCommunicationService".

Cmd Name
0 #GetState
1 #GetNetworkInfo
2 #GetIpv4Address
3 #GetDisconnectReason
4 #GetSecurityParameter
5 #GetNetworkConfig
100 #AttachStateChangeEvent
101 #GetNetworkInfoLatestUpdate
102 #Scan
103 #ScanPrivate
104 [5.0.0+] #SetWirelessControllerRestriction
200 #OpenAccessPoint
201 #CloseAccessPoint
202 #CreateNetwork
203 #CreateNetworkPrivate
204 #DestroyNetwork
205 #Reject
206 #SetAdvertiseData
207 #SetStationAcceptPolicy
208 #AddAcceptFilterEntry
209 #ClearAcceptFilter
300 #OpenStation
301 #CloseStation
302 #Connect
303 #ConnectPrivate
304 #Disconnect
400 #InitializeSystem
401 #FinalizeSystem
402 [4.0.0+] #SetOperationMode
403 [7.0.0+] #InitializeSystem2

GetState

No input, returns an output u32.

sdknso implements this by returning the u32, with 0 being returned on error / when service isn't initialized.

Value Description
0 None
1 Initialized
2 AccessPointOpened
3 AccessPointCreated
4 StationOpened
5 StationConnected
6 Invalid

GetNetworkInfo

Takes a type-0x1A output buffer containing a #NetworkInfo.

GetIpv4Address

No input, returns an output #Ipv4Address and a #SubnetMask.

GetDisconnectReason

No input, returns an output s16.

sdknso implements this by returning the s16 as a s32, with -1 being returned on error.

Value Description
-1 See above.
0 None
1 User
2 SystemRequest
3 DestroyedByAdmin
4 DestroyedBySystemRequest
5 Admin
6 SignalLost

GetSecurityParameter

No input, returns an output #SecurityParameter.

GetNetworkConfig

No input, returns an output #NetworkConfig.

AttachStateChangeEvent

No input, returns an output Event handle.

sdknso uses EventClearMode=1 with this. sdknso will Abort if this cmd fails.

GetNetworkInfoLatestUpdate

Takes a type-0x1A output buffer containing a #NetworkInfo and a type-0xA output buffer containing an array of #NodeLatestUpdate.

The array count must be 8.

Scan

Takes a type-0x22 output buffer containing an array of #NetworkInfo, a s16 channel, a #ScanFilter, returns an output s16 total_out.

sdknso copies the output s16 to a s32, the value passed for the input s16 is from an user-specified s32 (user-apps generally use value 0 for this).

This is the same as #ScanPrivate, except this also has the same channel-override functionality as #CreateNetwork.

State must be 3-5.

The array count must be at least 1. This is clamped to a maximum of 0x18.

ScanPrivate

Takes a type-0x22 output buffer containing an array of #NetworkInfo, a s16 channel, a #ScanFilter, returns an output s16 total_out.

sdknso copies the output s16 to a s32, the value passed for the input s16 is from an user-specified s32.

See #Scan.

SetWirelessControllerRestriction

Takes an input #WirelessControllerRestriction, no output.

State must be 1.

OpenAccessPoint

No input/output.

State must be 1, this cmd eventually sets the State to value 2.

CloseAccessPoint

No input/output.

State must be 2-3, this cmd eventually sets the State to value 1.

CreateNetwork

Takes an input #SecurityConfig, an #UserConfig, a #NetworkConfig, no output.

This is the same as #CreateNetworkPrivate, except the #AddressEntry params are 0, and the #SecurityParameter is generated from "nn::util::TinyMt::GenerateRandomBytes".

Unlike CreateNetworkPrivate, this overwrites the channel field in the #NetworkConfig. When the cached IsDevelopment value is true, the output from GetLdnChannel will overwrite that field if the s32 setting value is >=0, otherwise the original value is used. Otherwise when the IsDevelopment field is false (retail), the channel is overwritten with value 0.

This overwrites the u16 field at #SecurityConfig+0. When the cached IsDevelopment value is false (retail), value 1 is used, otherwise the original value is used.

State must be 2, this cmd eventually sets the State to value 3.

CreateNetworkPrivate

Takes an input #SecurityConfig, a #SecurityParameter, an #UserConfig, a #NetworkConfig, a type-0x9 input buffer containing an array of #AddressEntry, no output.

The buffer/count for #AddressEntry can be 0, in which case the network will be non-Private like #CreateNetwork. The count must be <=8.

See #CreateNetwork.

DestroyNetwork

No input/output.

State must be 3, this cmd eventually sets the State to value 2.

Reject

Takes an input #Ipv4Address, no output.

State must be 3.

SetAdvertiseData

Takes a type-0x21 input buffer, no output.

The input buffer contains arbitrary user data.

The buffer size must be <=0x180. An empty buffer (addr=NULL/size=0) can be used to reset the AdvertiseData size in state to zero.

State must be 2-3.

SetStationAcceptPolicy

Takes an input #AcceptPolicy, no output.

State must be 2-3.

AddAcceptFilterEntry

Takes an input #MacAddress, no output.

There are two sdknso funcs implementing this: one which takes a #MacAddress directly, the other loads the #MacAddress from the input #NodeInfo.

State must be 2-3.

ClearAcceptFilter

No input/output.

State must be 2-3.

OpenStation

No input/output.

State must be 1, this cmd eventually sets the State to value 4.

CloseStation

No input/output.

State must be 4-5, this cmd eventually sets the State to value 1.

Connect

Takes a type-0x19 input buffer containing a #NetworkInfo, a #SecurityConfig, an #UserConfig, a s32 LocalCommunicationVersion, a #ConnectOption, no output.

State must be 4, this cmd eventually sets the State to value 5.

This is identical to #ConnectPrivate (besides the below), except the data internally passed for #SecurityParameter/#NetworkConfig are loaded from the input #NetworkInfo.

This overwrites the u16 field at #SecurityConfig+0. When the cached IsDevelopment value is false (retail), value 1 is used, otherwise the used value is: original_field == 0 ? {u16 #NetworkInfo+0x60} : original_field.

u32 LocalCommunicationVersion>>15 must be 0.

ConnectPrivate

Takes a #SecurityConfig, #SecurityParameter, an #UserConfig, a s32 LocalCommunicationVersion, a #ConnectOption, a #NetworkConfig, no output.

See #Connect.

This overwrites the u16 field at #SecurityConfig+0. When the cached IsDevelopment value is false (retail), value 1 is used, otherwise the original value is used.

Disconnect

No input/output.

State must be 5, this cmd eventually sets the State to value 4.

InitializeSystem

Takes an input PID and an u64 pid_placeholder.

This is used immediately after object creation.

With [7.0.0+] #InitializeSystem2 is used instead.

FinalizeSystem

No input/output.

This is used during service exit, prior to closing the object. Official sw will Abort if this fails.

If State is set for it, this will run the equivalent of #CloseAccessPoint/#CloseStation when needed.

State must be non-zero, this cmd eventually sets the State to value 0.

SetOperationMode

Takes an input #OperationMode, no output.

State must be 1.

InitializeSystem2

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 #InitializeSystem.

State must be 0, this cmd eventually sets the State to value 1.

ldn:u

This is "nn::ldn::detail::IUserServiceCreator".

Cmd Name
0 #CreateUserLocalCommunicationService

CreateUserLocalCommunicationService

Returns an #IUserLocalCommunicationService.

The user-process closes the IUserServiceCreator object immediately after using this cmd. Official sw ignores errors from this cmd.

IUserLocalCommunicationService

This is "nn::ldn::detail::IUserLocalCommunicationService".

Cmd Name
0 #GetState
1 #GetNetworkInfo
2 #GetIpv4Address
3 #GetDisconnectReason
4 #GetSecurityParameter
5 #GetNetworkConfig
100 #AttachStateChangeEvent
101 #GetNetworkInfoLatestUpdate
102 #Scan
103 #ScanPrivate
104 [5.0.0+] #SetWirelessControllerRestriction
200 #OpenAccessPoint
201 #CloseAccessPoint
202 #CreateNetwork
203 #CreateNetworkPrivate
204 #DestroyNetwork
205 #Reject
206 #SetAdvertiseData
207 #SetStationAcceptPolicy
208 #AddAcceptFilterEntry
209 #ClearAcceptFilter
300 #OpenStation
301 #CloseStation
302 #Connect
303 #ConnectPrivate
304 #Disconnect
400 #Initialize
401 #Finalize
402 [7.0.0+] #Initialize2

Initialize

Takes an input PID and an u64 pid_placeholder.

This is used immediately after object creation.

With [7.0.0+] #Initialize2 is used instead.

Finalize

No input/output.

This is used during service exit, prior to closing the object. Official sw will Abort if this fails.

Initialize2

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.

ndd

This is "nn::ndd::IService".

This was added with [5.0.0] and removed with [6.0.0].

Cmd Name
0 EnableAutoCommunication
1 DisableAutoCommunication
2 IsAutoCommunicationEnabled
3 EnablePowerSave
4 DisablePowerSave
5 IsPowerSaveEnabled
6 IsNetworkActive
7 AcquireSendDataUpdateEvent
8 AddSendData
9 ClearSendData
10 GetSendData
11 AcquireReceiveDataEvent
12 GetCurrentReceiveDataCounter
13 GetOldestReceiveDataCounter
14 GetNextReceiveDataCounter
15 GetAvailableReceiveDataCount
16 GetRecentReceiveDataCounter
17 GetReceiveData
18 AddReceiveData
19 ClearReceiveData
20 ClearDataIdFilter
21 AcquireDeviceScanEvent
22 StartDeviceScan
23 CancelDeviceScan
24 GetDeviceScanResult

lp2p:app, lp2p:sys

These are "nn::lp2p::detail::INetworkServiceCreator".

These were added with [9.0.0+].

Cmd Name
0 CreateNetworkService
8 CreateNetworkServiceMonitor

INetworkService

This is "nn::lp2p::detail::INetworkService".

Cmd Name
0 Initialize
[9.0.0-9.0.1] 256 AttachNetworkInterfaceStateChangeEvent
[9.0.0-9.0.1] 264 GetNetworkInterfaceLastError
[9.0.0-9.0.1] 272 GetRole
[9.0.0-9.0.1] 280
[9.0.0-9.0.1] 288 GetGroupInfo
[9.0.0-9.0.1] 296
[9.0.0-9.0.1] 304
[9.0.0-9.0.1] 312
[9.0.0-9.0.1] 320
512
768
776
784
1536 SendToOtherGroup
1544 RecvFromOtherGroup
1552 AddAcceptableGroupId
1560 [9.1.0+]

Initialize

Returns 0.

INetworkServiceMonitor

This is "nn::lp2p::detail::INetworkServiceMonitor".

This interface has no commands, until [9.1.0+] which added actual commands.

Cmd Name
0 Initialize
256 AttachNetworkInterfaceStateChangeEvent
264 GetNetworkInterfaceLastError
272 GetRole
280
281
288 GetGroupInfo
296
304
312
320
328 AttachJoinEvent
336

Initialize

Returns 0.

lp2p:m

This is "nn::lp2p::detail::IMonitorServiceCreator".

This was added with [9.1.0+].

Cmd Name
0 #CreateMonitorService

CreateMonitorService

Takes a PID, a total of 0x10-bytes of input, and returns an #IMonitorService.

IMonitorService

This is "nn::lp2p::detail::IMonitorService".

Cmd Name
0 Initialize
288 GetGroupInfo
320

Initialize

Returns 0.

Ipv4Address

This is "nn::ldn::Ipv4Address". This is a 0x4-byte struct with 4-byte alignment.

This is essentially the same as struct in_addr.

SubnetMask

This is "nn::ldn::SubnetMask". This is a 0x4-byte struct with 4-byte alignment.

This is essentially the same as struct in_addr.

Ssid

This is "nn::ldn::Ssid".

When converting a Ssid to a string, the loaded chars from the string must be in the range of 0x20-0x7F, otherwise the byte written to the string will be 0.

Offset Size Description
0x0 0x1 Length excluding NUL-terminator, must be 0x1-0x20.
0x1 0x21 SSID string including NUL-terminator, str[{above length}] must be 0.

NetworkInfo

This is "nn::ldn::NetworkInfo". This is a 0x480-byte struct. The data at +0x50 is another struct.

Offset Size Description
0x0 0x8 LocalCommunicationId
0x8 0x2
0xA 0x2
0xC 0x4
0x10 0x10 Last 0x10-bytes of #SecurityParameter.
0x20 0x6 #MacAddress
0x26 0x22 #Ssid. After filtering with #Scan when +0x4B is value 0x2, this is overwritten with data converted from +0x10.
0x48 0x2 Channel
0x4A 0x1
0x4B 0x1
0x4C 0x4
0x50 0x10 First 0x10-bytes of #SecurityParameter.
0x60 0x2 Same as #SecurityConfig+0x0.
0x62 0x4
0x66 0x1
0x67 0xD
0x74 0x20 First 0x20-bytes of #UserConfig.
0x94 0x2
0x96 0x2 s16 LocalCommunicationVersion
0x98 0x1D2
0x26A 0x2 AdvertiseData size
0x26C 0x180 AdvertiseData
0x3EC 0x8C
0x478 0x8

ScanFilter

This is "nn::ldn::ScanFilter". This is a 0x60-byte struct with 8-byte alignment.

sdknso copies the input ScanFilter to a tmp struct on stack, which is then used with the cmd.

Offset Size Description
0x0 0x8 When enabled, this will be overwritten if it's -1. The data written for this is the first LocalCommunicationId for the user-process loaded via arp:r, if loading fails value 0 is written instead. During filtering if enabled, u8 #NetworkInfo+0x4B must match 0x2, and this ScanFilter field must match #NetworkInfo+0x0.
0x8 0x2 Padding
0xA 0x2 During filtering if enabled, u8 #NetworkInfo+0x4B must match 0x2, and this ScanFilter field must match #NetworkInfo+0xA.
0xC 0x4 Padding
0x10 0x10 During filtering if enabled, u8 #NetworkInfo+0x4B must match 0x2, and this ScanFilter data must match #NetworkInfo+0x10.
0x20 0x4 When enabled, must be <=0x3, and during filtering must match u8 #NetworkInfo+0x4B.
0x24 0x6 #MacAddress. Only copied with #ScanPrivate. During filtering if enabled, this must match #NetworkInfo+0x20.
0x2A 0x22 #Ssid. During filtering if enabled, this must match #NetworkInfo+0x26 (the #Ssid there must be valid for this as well). The strings are compared, without verifying the length field in #Ssid matches.
0x4C 0x10 Cleared to zero for the tmp struct.
0x5C 0x4 Flags. Masked with 0x37 for #Scan, with #ScanPrivate this is masked with 0x3F.

Flags:

Bit Description
0 When set, enables using ScanFilter+0.
1 When set, enables using ScanFilter+0x10.
2 When set, enables using ScanFilter+0x20.
3 When set, enables using the ScanFilter #MacAddress.
4 When set, enables using the ScanFilter #Ssid.
5 When set, enables using ScanFilter+0xA.

NetworkConfig

This is "nn::ldn::NetworkConfig". This is a 0x20-byte struct with 8-byte alignment.

sdknso copies the input NetworkConfig to a tmp struct on stack, which is then used with the cmd (#CreateNetwork, #CreateNetworkPrivate, #ConnectPrivate).

Offset Size Description
0x0 0x8 LocalCommunicationId. Same as #NetworkInfo+0x0. #CreateNetwork/#CreateNetworkPrivate/#Connect/#ConnectPrivate: When -1, this is overwritten with the first LocalCommunicationId for the user-process loaded via arp:r, if loading fails value 0 is written instead. Otherwise when not -1, if control.nacp loading is successful with arp:r, this field must match one of the LocalCommunicationIds from there otherwise an error is thrown.
0x8 0x2 Cleared to zero during the copy.
0xA 0x2 Same as #NetworkInfo+0xA.
0xC 0x4 Cleared to zero during the copy.
0x10 0x2 s16 Channel, can be zero. Same as #NetworkInfo+0x48.
0x12 0x1 s8. Same as #NetworkInfo+0x66. #CreateNetwork/#CreateNetworkPrivate: Must be 0x1-0x8.
0x13 0x1 Cleared to zero during the copy.
0x14 0x2 Same as #NetworkInfo+0x96. Must not be negative.
0x16 0xA Cleared to zero during the copy.

NodeLatestUpdate

This is "nn::ldn::NodeLatestUpdate". This is a 0x8-byte struct.

Offset Size Description
0x0 0x1 Flag, the field in state is reset to zero by #GetNetworkInfoLatestUpdate after loading it.
0x1 0x7 Not initialized with #GetNetworkInfoLatestUpdate.

WirelessControllerRestriction

This is "nn::ldn::WirelessControllerRestriction". This is an u32 enum.

Value Description
0
1

SecurityConfig

This is "nn::ldn::SecurityConfig". This is a 0x44-byte struct with 2-byte alignment.

Offset Size Description
0x0 0x2 Overwritten by #CreateNetwork/#CreateNetworkPrivate and #Connect/#ConnectPrivate. The value used internally by these cmds must be 0x1-0x3.
0x2 0x2 Must be 0x10-0x40.
0x4 0x40

SecurityParameter

This is "nn::ldn::SecurityParameter". This is a 0x20-byte struct with 1-byte alignment.

UserConfig

This is "nn::ldn::UserConfig". This is a 0x30-byte struct with 1-byte alignment.

sdknso copies the input UserConfig to a tmp struct on stack, which is then used with the cmd.

Offset Size Description
0x0 0x20 NUL-terminated string for the user nickname.
0x20 0x10 Cleared to zero during the copy.

AddressEntry

This is "nn::ldn::AddressEntry". This is a 0xC-byte struct.

Offset Size Description
0x0 0x4 #Ipv4Address
0x4 0x6 #MacAddress
0xA 0x2 Padding

AcceptPolicy

This is "nn::ldn::AcceptPolicy". This is an u8.

Value Description
0
1
2
3

MacAddress

This is "nn::ldn::MacAddress". This is a 6-byte struct with 1-byte alignment.

NodeInfo

This is "nn::ldn::NodeInfo".

Offset Size Description
0x0 0x4 #Ipv4Address
0x4 0x6 #MacAddress

ConnectOption

This is "nn::ldn::ConnectOption". This is an u32 bitmask.

There's two versions of the sdknso funcs for #Connect/#ConnectPrivate: the version where the ConnectOption isn't user-specified uses a default value of 0x1 for it, with the same ShowError code without the bit0 check.

When bit0 here is set after using the above cmds, the sdknso funcs will use ShowError with the returned Result if: (rc & 0x3FE1FF) == 0xE0CB.

This must be <=0x1, besides this validation ConnectOption is ignored by #Connect/#ConnectPrivate.

OperationMode

This is "nn::ldn::OperationMode". This is an u32 enum.

Value Description
0
1