-
Notifications
You must be signed in to change notification settings - Fork 98
WinBox Native connection
Alpha-preview. This transport is the newest and least battle-tested in tik4net. The API/field mapping is reconstructed from the WinBox
.jgcatalog and covers common tables, but exotic tables/verbs may need aPathOverride/FieldOverride, and details may still change. For production use prefer the API or, on the WinBox channel, the WinBox CLI transport. Bug reports and mapping fixes are welcome.
WinBox Native (TikConnectionType.WinboxNative) connects over the encrypted WinBox channel on TCP
port 8291 — the same port and crypto as the WinBox application — but instead of driving a terminal it
issues structured M2 protocol calls (the binary key–value messages WinBox itself uses). CRUD maps
directly to the native getall / get / set / add / remove / move handlers, so there is no CLI
screen-scraping involved.
Authentication is identical to WinBox CLI: EC-SRP5 + AES-128-CBC (legacy MD5
fallback for RouterOS < 6.43). The difference is purely above the channel: native M2 vs. a mepty
terminal.
using System.Linq;
using tik4net;
using (var conn = ConnectionFactory.OpenConnection(
TikConnectionType.WinboxNative, "192.168.4.1", "admin", ""))
{
var ifaces = conn.LoadAll<tik4net.Objects.Interface.Interface>().ToList();
foreach (var i in ifaces)
conn.CreateCommandAndParameters("/interface/set", ".id", i.Id, "comment", "managed").ExecuteNonQuery();
}Via TikConnectionSetup — the recommended way, because its configure callback runs before the
connection opens, which is exactly where the mapping overrides below must be set:
var setup = new TikConnectionSetup("192.168.4.1", "admin", "");
using (var conn = setup.CreateWinboxNativeConnection(c =>
{
c.PathOverride("/ppp/secret", new[] { 27, 101 });
c.CatalogCachePath = @"C:\ProgramData\myapp\winbox-cache";
}))
{
// ...
}
// async
using (var conn = await setup.CreateWinboxNativeConnectionAsync())
{
// ...
}Direct construction also works (set the properties below, then Open):
using tik4net.WinboxNative;
var conn = new WinboxNativeConnection { ConnectTimeout = 10000 };
conn.Open("192.168.4.1", "admin", "");The CLI transports (Telnet / MAC-Telnet / WinBox CLI) parse print as-value text. Native M2 avoids the
terminal entirely: it is faster, has no prompt/echo/paging edge cases, and is closer to how the WinBox GUI
talks to the router. The trade-off is the mapping problem described next.
The MikroTik API addresses things by text: a path like /ip/firewall/filter and field names like
src-address or connection-state. The WinBox M2 protocol addresses the same things by numbers: a
handler array like [20,3] and integer field keys like 0xFE0009. To make the O/R mapper work unchanged,
WinboxNativeConnection must translate API path → handler and API field name → numeric key (and
back) — and that mapping is genuinely awkward for two reasons:
- The numbers are version-volatile. Handler minors and field keys shift between RouterOS releases as menus and fields are added. Hard-coding them would rot.
-
WinBox stores GUI labels, not API names. The catalog calls a window "DNS Static Entry" (API
/ip/dns/static), "Firewall Rule" (API/ip/firewall/filter), "Resources" (API/system/resource). WinBox never stores the API leaf, so the two cannot be derived from each other mechanically in every case.
The design splits the mapping by stability, so the volatile half is always read live and only the stable (text) half is shipped:
| What | Stability | Source |
|---|---|---|
| Handler number, field key / type / read-only | volatile (changes per version) |
read live from the version-matched .jg catalog the router serves, fetched once over the same WinBox channel and cached |
| API field name ↔ label | stable text | a normalizer (lower-case, spaces→-) over the live labels, + a small built-in alias dictionary for irregular labels |
| API path ↔ handler | stable text → volatile number | the menu tree in the live .jg (handler is always live); a small built-in alias bridges irregular paths to their menu label |
Protocol constants (getall cmd, .id, comment, disabled keys) |
fixed | hard-coded |
So: handler/field numbers are never hard-coded — they come from the router's own .jg for its version.
Only the English text bridge is shipped (a hard-coded dictionary), and it is the thing that carries across
versions. Typed values (IP addresses, MACs, enums, interface references) are encoded/decoded from the .jg
field type — e.g. an IP packs to a u32, an interface reference resolves to/from the target object's name.
If a field name or path can't be resolved (an unusual label, or a table the built-in dictionary doesn't cover), the connection throws a guiding exception rather than guessing:
- unknown path →
TikNoSuchCommandException("no M2 handler mapping for path … — add aPathOverrideor use a WinboxCli connection") - unknown field →
WinboxFieldResolutionException("cannot resolve API field … — add aFieldOverrideor use a WinboxCli connection")
You resolve these per session with the overrides below.
Both overrides take priority over the live catalog and the built-in dictionary, and are keyed on stable text so they survive router upgrades.
using tik4net.WinboxNative;
var conn = new WinboxNativeConnection();
// 1) Map an API path to a WinBox handler [major, minor] when the built-in alias doesn't cover it.
conn.PathOverride("/ppp/secret", new[] { 27, 101 });
// 2) Map an API field name to its numeric M2 key for a given path.
conn.FieldOverride("/ip/hotspot/user", "mac-address", 0x1);
conn.Open("192.168.4.1", "admin", "");Tip — finding the numbers. The
.jgcatalogs WinBox caches under%APPDATA%\MikroTik\WinBox\<version>\*.jg(and the copy tik4net caches underCatalogCachePath) are plain JavaScript object literals: a window'spath:[a,b]is the handler, and a field'sid:'s10006'encodes the key (0x10006) and type (s=string). Match the window/field by its label to read off the numbers.
The fetched .jg set is cached per router version so it isn't downloaded on every connect:
var conn = new WinboxNativeConnection
{
CatalogCachePath = @"C:\ProgramData\myapp\winbox-cache" // default: %TEMP%\tik4net
};Files land in <CatalogCachePath>\<routerVersion>\*.jg. Only the base roteros.jg is required; the
feature plugins (ppp.jg, hotspot.jg, dhcp.jg, …) are optional and only present for packages the router
actually has — calling into a path whose plugin is absent yields TikNoSuchCommandException ("no such
command"), exactly like the router would answer.
Native errors are surfaced with the router's own message and translated to the same exception types as the API/CLI transports, so existing error-handling code keeps working:
| Router result | tik4net exception |
|---|---|
already have such address / already-exists |
TikAlreadyHaveSuchItemException |
object doesn't exist / unresolvable .id
|
TikNoSuchItemException |
| unmapped path / missing plugin | TikNoSuchCommandException |
| other M2 errors |
TikCommandUnexpectedResponseException (message includes the router's error string) |
CRUD only — like the CLI transports. Streaming / Listen / Async (ExecuteAsync, LoadAsync, Torch) throw
NotSupportedException; use the API or REST transport for those.
bool hasCrud = conn.Supports(TikConnectionCapability.Crud); // true
bool hasListen = conn.Supports(TikConnectionCapability.Listen); // falseBoth use the same encrypted WinBox channel (TCP 8291, EC-SRP5 + AES). They differ above the channel:
WinBox Native (WinboxNative) |
WinBox CLI (WinboxCli) |
|
|---|---|---|
| How CRUD works | structured M2 calls (no terminal) | drives the RouterOS CLI via the mepty terminal |
| Field mapping | API ↔ M2 keys via the live .jg + dictionary |
none — uses CLI text directly |
| Coverage | broad, but exotic tables/verbs may need an override | every command the CLI accepts |
| Speed | no prompt/echo/paging overhead | terminal round-trips |
| Best when | you want clean structured CRUD on common tables | you need a command the native mapping doesn't cover yet, or full CLI parity |
WinBox CLI is the fallback whenever native mapping is incomplete for your
workload: it accepts any command the router's CLI does, at the cost of text parsing. The two are
interchangeable at the ITikConnection level, so switching is a one-line change to the
TikConnectionType / factory call.
The WinBox M2 protocol mapping was reconstructed from the official webfig /jsproxy client
(master*.js, which speaks the same M2 protocol in JSON) and the community reverse-engineering work
referenced on WinBox-CLI-connection.
- WinBox-CLI-connection — terminal-driven WinBox CRUD (the fallback)
- WinBox-CLI-MAC-connection — WinBox CLI over the MAC layer
- SSL-connection — encrypted binary API connection
-
MCP server — run M2 commands and see the raw M2 trace (
includeRawTrace) from an MCP client - Roadmap-4x — transport roadmap