From 0eff7800aeb524f490ddaf58282fed46a4d933b5 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Tue, 16 Aug 2016 20:36:46 -0700 Subject: Update protocol spec --- inform_protocol.md | 257 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 238 insertions(+), 19 deletions(-) diff --git a/inform_protocol.md b/inform_protocol.md index cadbe24..f06ddb3 100644 --- a/inform_protocol.md +++ b/inform_protocol.md @@ -1,5 +1,4 @@ -Ubiquiti Inform Protocol -======================== +# Ubiquiti Inform Protocol The mFi uses the Ubiquiti inform protocol to handle all communications to and from the controller. This is the way that it transmits the current state of the @@ -19,8 +18,7 @@ response instead of a noop response it will immediately do another inform; this continues until the controller sends the next noop response. Responses never appear to contain multiple commands. -Raw Packet Structure --------------------- +## Raw Packet Structure 4 bytes magic number integer 4 bytes version integer 6 bytes hwaddr string @@ -30,21 +28,19 @@ Raw Packet Structure 4 bytes data length integer n bytes AES encrypted payload string -Raw Packet Constraints ----------------------- +## Raw Packet Constraints magic must == 1414414933 data version must < 1 flags & 0x1 != 0 means encrypted flags & 0x2 != 0 means compressed -Payload Types -------------- +## Payload Types The payload is AES encrypted in CBC mode using PKCS5 padding. They key is the device auth key from the database or a master key that is hard coded if the device has not been provisioned yet. The master key is hard coded in the controller code in the DeviceManager class and pretty easy to find. -MASTER_KEY = "ba86f2bbe107c7c57eb5f2690775c712" + MASTER_KEY = "ba86f2bbe107c7c57eb5f2690775c712" On devices running protocol version 1 the encrypted payload is just JSON data. In version 0 of the protocol the data was key=value pairs separated by @@ -54,16 +50,11 @@ The payloads break down into two categories; those coming into the controller and those going out of the controller. -Output Payloads ---------------- +## Output Payloads Output payloads are those that originate from the controller and are bound for the device. These always appear to contain a _type field. I have observed the following output payloads. - "mgmt_cfg": "mgmt.is_default=false\nmgmt.authkey=41d6529fd555fbb1bdeeafeb995510fa\nmgmt.cfgversion=f1bb359840b519a4\nmgmt.servers.1.url=http://172.16.0.38:6080/inform\nmgmt.selfrun_guest=pass\nselfrun_guest=pass\ncfgversion=f1bb359840b519a4\n", - "port_cfg": "port.0.sensorId=52210822e4b0959e7fe94009\nvpower.1.rep_output=1\nvpower.1.rep_pf=1\nvpower.1.rep_energy_sum=1\nvpower.1.rep_v_rms=1\nvpower.1.rep_i_rms=1\nvpower.1.rep_active_pwr=1\nvpower.1.relay=1\nvpower.1.output_tag=output\nvpower.1.pf_tag=pf\nvpower.1.energy_sum_tag=energy_sum\nvpower.1.v_rms_tag=v_rms\nvpower.1.i_rms_tag=i_rms\nvpower.1.active_pwr_tag=active_pwr\nport.1.sensorId=5221082be4b0959e7fe9400a\nvpower.2.rep_output=1\nvpower.2.rep_pf=1\nvpower.2.rep_energy_sum=1\nvpower.2.rep_v_rms=1\nvpower.2.rep_i_rms=1\nvpower.2.rep_active_pwr=1\nvpower.2.relay=1\nvpower.2.output_tag=output\nvpower.2.pf_tag=pf\nvpower.2.energy_sum_tag=energy_sum\nvpower.2.v_rms_tag=v_rms\nvpower.2.i_rms_tag=i_rms\nvpower.2.active_pwr_tag=active_pwr\nport.2.sensorId=5221083be4b0959e7fe9400b\nvpower.3.rep_output=1\nvpower.3.rep_pf=1\nvpower.3.rep_energy_sum=1\nvpower.3.rep_v_rms=1\nvpower.3.rep_i_rms=1\nvpower.3.rep_active_pwr=1\nvpower.3.relay=0\nvpower.3.output_tag=output\nvpower.3.pf_tag=pf\nvpower.3.energy_sum_tag=energy_sum\nvpower.3.v_rms_tag=v_rms\nvpower.3.i_rms_tag=i_rms\nvpower.3.active_pwr_tag=active_pwr\n", - "system_cfg": "# users\nusers.status=enabled\nusers.1.name=admin\nusers.1.password=Mq9xt5C8DjcLA\nusers.1.status=enabled\n# bridge\nbridge.status=disabled\nbridge.1.devname=br0\nbridge.1.fd=1\nbridge.1.stp.status=disabled\nbridge.1.port.1.devname=eth1\nsnmp.status=disabled\nppp.status=disabled\npwdog.status=disabled\ndnsmasq.status=disabled\ndhcpd.status=disabled\nhttpd.status=disabled\nhttpd.port.http=80\nhttpd.port=80\nigmpproxy.status=disabled\ntelnetd.status=disabled\ntshaper.status=disabled\nnetmode=bridge\nntpclient.status=disabled\nntpclient.1.server=pool.ntp.org\nntpclient.1.status=disabled\nsyslog.status=enabled\nresolv.status=enabled\nresolv.host.1.name=OfficePowerStrip\nresolv.nameserver.1.status=disabled\nresolv.nameserver.2.status=disabled\ndhcpc.status=enabled\ndhcpc.1.status=enabled\ndhcpc.1.devname=eth1\nroute.status=enabled\nvlan.status=disabled\nradio.1.ack.auto=disabled\nradio.1.ackdistance=300\nradio.1.acktimeout=30\nradio.1.ampdu.status=enabled\nradio.1.clksel=1\nradio.1.countrycode=840\nradio.1.cwm.enable=0\nradio.1.cwm.mode=1\nradio.1.forbiasauto=0\nradio.1.channel=0\nradio.1.ieee_mode=11nght40\nradio.1.mcastrate=auto\nradio.1.mode=managed\nradio.1.puren=0\nradio.1.rate.auto=enabled\nradio.1.rate.mcs=auto\nradio.1.txpower=auto\n# wlans (radio)\nradio.status=enabled\nradio.countrycode=840\naaa.status=disabled\nwireless.status=enabled\ndhcpc.2.status=enabled\ndhcpc.2.devname=ath0\nbridge.1.port.2.devname=ath0\nradio.1.devname=ath0\nradio.1.status=enabled\naaa.1.br.devname=br0\naaa.1.devname=ath0\naaa.1.driver=madwifi\naaa.1.ssid=\naaa.1.status=disabled\nwireless.1.mode=managed\nwireless.1.devname=ath0\nwireless.1.status=enabled\nwireless.1.authmode=1\nwireless.1.l2_isolation=disabled\nwireless.1.is_guest=false\nwireless.1.security=none\nwireless.1.addmtikie=disabled\nwireless.1.ssid=\nwireless.1.hide_ssid=enabled\nwireless.1.mac_acl.status=disabled\nwireless.1.mac_acl.policy=deny\nwireless.1.wmm=enabled\n# netconf\nnetconf.status=enabled\nnetconf.1.devname=eth1\nnetconf.1.autoip.status=disabled\nnetconf.1.ip=0.0.0.0\nnetconf.1.promisc=enabled\nnetconf.1.status=enabled\nnetconf.1.up=enabled\nnetconf.2.devname=br0\nnetconf.2.autoip.status=disabled\nnetconf.2.ip=0.0.0.0\nnetconf.2.status=enabled\nnetconf.2.up=enabled\nnetconf.3.devname=ath0\nnetconf.3.autoip.status=disabled\nnetconf.3.ip=0.0.0.0\nnetconf.3.promisc=enabled\nnetconf.3.status=enabled\nnetconf.3.up=enabled\nqos.status=enabled\nqos.group.1.rate=100\nqos.group.2.rate=100\nqos.group.6.rate=100\nqos.if.1.devname=eth1\nqos.if.1.devspeed=100\nqos.if.1.group=1\nqos.if.2.devname=ath0\nqos.if.2.devspeed=150\nqos.if.2.group=20\n" - _type: firmware upgrade (upgrade) url: full url to firmware.bin datetime: rfc3339 formatted date, server time @@ -115,11 +106,12 @@ following output payloads. // val and volt set to 1 to turn on, 0 to turn off -Input Payloads --------------- +## Input Payloads Incoming packets appear to be a JSON version of the out put of the `mca-dump` -command on the device. There is definitely some AirOS legacy in here. I do not -document the whole input payload since most of it is not interesting. +command on the device. There is definitely some Unifi legacy in here. It +appears that mFi is just using the Unfi firmware and has hacked it a bit for +their use-case so most of the fields outside of alarm are not relevant to the +mFi use-case. callback from device: javascript object alarm: list of sensors @@ -138,6 +130,52 @@ document the whole input payload since most of it is not interesting. type: sensor type (output, analog, rmsSum, rms) val: value (float) + if_table: list of interfaces and stats + ip: interface ip + mac: interface mac address + name: interface device name (dev handle) + rx_bytes: bytes received on the interface + rx_dropped: packets dropped by the interface + rx_errors: receive errors on the interface + rx_packets: packets received on the interface + tx_bytes: bytes transmitted by the interface + tx_dropped: trasmit drops on the interface + tx_errors: transmit errors on the interface + tx_packets: number of packets transmitted by the interface + type: appears to be the same as name + + radio_table: list of radios in the device + builtin_ant_gain: gain of builtin antenna + builtin_antenna: boolean, does device have antenna + max_txpower: maximum transmit power + name: name of radio + radio: radio type (ex: ng) + scan_table: list, unknown + + vap_table: table of joined wireless networks + bssid: network SSID + ccq: client connection qality + channel: channel number + essid: network friendly name + id: mode? (ex: user) + name: uplink device name + num_sta: number of connected stations (always 0) + radio: radio type (ex: ng) + rx_bytes: bytes received on the interface + rx_dropped: packets dropped by the interface + rx_errors: receive errors on the interface + rx_packets: packets received on the interface + tx_bytes: bytes transmitted by the interface + tx_dropped: trasmit drops on the interface + tx_errors: transmit errors on the interface + tx_packets: number of packets transmitted by the interface + rx_crypts: unknown + rx_frags: received fragmented packets + rx_nwids: received network beacons + tx_power: transmitting power of the radio (assumed in dBm) + tx_retries: number of transmit retries on interface + usage: same as id + hostname: hostname of device ("ubnt" unless changed) ip: IP of device mac: mac address of primary interface @@ -148,3 +186,184 @@ document the whole input payload since most of it is not interesting. uptime: uptime in seconds since last reboot version: firmware version default: boolean, device is unconfigured + cfgversion: string, unknown (ex: c3846443e1b4860b) + guest_token: string, unknown (ex: 364E8B215D16AB963A53232E3873000C) + inform_url: string, url to which the device is reporting + isolated: boolean, can the device reach the rest of the network + localversion: string, unknown (ex: ?) + locating: boolean, is the device in locating mode (blinking LED) + portversion: string, unknown (ex: 443eb55240f26367) + time: integer, device time as unix timestamp + trackable: boolean as string, unknown + uplink: string, unix device name (dev handle) of the primary uplink device + + +## Config Samples +These are some observed configuration payloads for the configuration packets. + +### mgmt cfg + mgmt.is_default=false + mgmt.authkey=41d6529fd555fbb1bdeeafeb995510fa + mgmt.cfgversion=f1bb359840b519a4 + mgmt.servers.1.url=http://172.16.0.38:6080/inform + mgmt.selfrun_guest=pass + selfrun_guest=pass + cfgversion=f1bb359840b519a4 + + +### port cfg + port.0.sensorId=52210822e4b0959e7fe94009 + vpower.1.rep_output=1 + vpower.1.rep_pf=1 + vpower.1.rep_energy_sum=1 + vpower.1.rep_v_rms=1 + vpower.1.rep_i_rms=1 + vpower.1.rep_active_pwr=1 + vpower.1.relay=1 + vpower.1.output_tag=output + vpower.1.pf_tag=pf + vpower.1.energy_sum_tag=energy_sum + vpower.1.v_rms_tag=v_rms + vpower.1.i_rms_tag=i_rms + vpower.1.active_pwr_tag=active_pwr + port.1.sensorId=5221082be4b0959e7fe9400a + vpower.2.rep_output=1 + vpower.2.rep_pf=1 + vpower.2.rep_energy_sum=1 + vpower.2.rep_v_rms=1 + vpower.2.rep_i_rms=1 + vpower.2.rep_active_pwr=1 + vpower.2.relay=1 + vpower.2.output_tag=output + vpower.2.pf_tag=pf + vpower.2.energy_sum_tag=energy_sum + vpower.2.v_rms_tag=v_rms + vpower.2.i_rms_tag=i_rms + vpower.2.active_pwr_tag=active_pwr + port.2.sensorId=5221083be4b0959e7fe9400b + vpower.3.rep_output=1 + vpower.3.rep_pf=1 + vpower.3.rep_energy_sum=1 + vpower.3.rep_v_rms=1 + vpower.3.rep_i_rms=1 + vpower.3.rep_active_pwr=1 + vpower.3.relay=0 + vpower.3.output_tag=output + vpower.3.pf_tag=pf + vpower.3.energy_sum_tag=energy_sum + vpower.3.v_rms_tag=v_rms + vpower.3.i_rms_tag=i_rms + vpower.3.active_pwr_tag=active_pwr + + +### system cfg + # users + users.status=enabled + users.1.name=admin + users.1.password=Mq9xt5C8DjcLA + users.1.status=enabled + # bridge + bridge.status=disabled + bridge.1.devname=br0 + bridge.1.fd=1 + bridge.1.stp.status=disabled + bridge.1.port.1.devname=eth1 + snmp.status=disabled + ppp.status=disabled + pwdog.status=disabled + dnsmasq.status=disabled + dhcpd.status=disabled + httpd.status=disabled + httpd.port.http=80 + httpd.port=80 + igmpproxy.status=disabled + telnetd.status=disabled + tshaper.status=disabled + netmode=bridge + ntpclient.status=disabled + ntpclient.1.server=pool.ntp.org + ntpclient.1.status=disabled + syslog.status=enabled + resolv.status=enabled + resolv.host.1.name=OfficePowerStrip + resolv.nameserver.1.status=disabled + resolv.nameserver.2.status=disabled + dhcpc.status=enabled + dhcpc.1.status=enabled + dhcpc.1.devname=eth1 + route.status=enabled + vlan.status=disabled + radio.1.ack.auto=disabled + radio.1.ackdistance=300 + radio.1.acktimeout=30 + radio.1.ampdu.status=enabled + radio.1.clksel=1 + radio.1.countrycode=840 + radio.1.cwm.enable=0 + radio.1.cwm.mode=1 + radio.1.forbiasauto=0 + radio.1.channel=0 + radio.1.ieee_mode=11nght40 + radio.1.mcastrate=auto + radio.1.mode=managed + radio.1.puren=0 + radio.1.rate.auto=enabled + radio.1.rate.mcs=auto + radio.1.txpower=auto + # wlans (radio) + radio.status=enabled + radio.countrycode=840 + aaa.status=disabled + wireless.status=enabled + dhcpc.2.status=enabled + dhcpc.2.devname=ath0 + bridge.1.port.2.devname=ath0 + radio.1.devname=ath0 + radio.1.status=enabled + aaa.1.br.devname=br0 + aaa.1.devname=ath0 + aaa.1.driver=madwifi + aaa.1.ssid= + aaa.1.status=disabled + wireless.1.mode=managed + wireless.1.devname=ath0 + wireless.1.status=enabled + wireless.1.authmode=1 + wireless.1.l2_isolation=disabled + wireless.1.is_guest=false + wireless.1.security=none + wireless.1.addmtikie=disabled + wireless.1.ssid= + wireless.1.hide_ssid=enabled + wireless.1.mac_acl.status=disabled + wireless.1.mac_acl.policy=deny + wireless.1.wmm=enabled + # netconf + netconf.status=enabled + netconf.1.devname=eth1 + netconf.1.autoip.status=disabled + netconf.1.ip=0.0.0.0 + netconf.1.promisc=enabled + netconf.1.status=enabled + netconf.1.up=enabled + netconf.2.devname=br0 + netconf.2.autoip.status=disabled + netconf.2.ip=0.0.0.0 + netconf.2.status=enabled + netconf.2.up=enabled + netconf.3.devname=ath0 + netconf.3.autoip.status=disabled + netconf.3.ip=0.0.0.0 + netconf.3.promisc=enabled + netconf.3.status=enabled + netconf.3.up=enabled + qos.status=enabled + qos.group.1.rate=100 + qos.group.2.rate=100 + qos.group.6.rate=100 + qos.if.1.devname=eth1 + qos.if.1.devspeed=100 + qos.if.1.group=1 + qos.if.2.devname=ath0 + qos.if.2.devspeed=150 + qos.if.2.group=20 -- cgit v1.2.3