88 lines
2.4 KiB
Lua
88 lines
2.4 KiB
Lua
--- Functions for communicating with Konnex (KNX) devices
|
|
--
|
|
-- @author Niklaus Schiess, Dominik Schneider
|
|
-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html
|
|
-- @class module
|
|
-- @name knx
|
|
|
|
local ipOps = require "ipOps"
|
|
local string = require "string"
|
|
local _ENV = {}
|
|
|
|
knxServiceFamilies = {
|
|
[0x02]="KNXnet/IP Core",
|
|
[0x03]="KNXnet/IP Device Management",
|
|
[0x04]="KNXnet/IP Tunnelling",
|
|
[0x05]="KNXnet/IP Routing",
|
|
[0x06]="KNXnet/IP Remote Logging",
|
|
[0x08]="KNXnet/IP Object Server",
|
|
[0x07]="KNXnet/IP Remote Configuration and Diagnosis"
|
|
}
|
|
|
|
knxDibDescriptionTypes = {
|
|
[0x01]="Device Information",
|
|
[0x02]="Supp_Svc_families",
|
|
[0x03]="IP_Config",
|
|
[0x04]="IP_Cur_Config",
|
|
[0x05]="IP_Config"
|
|
}
|
|
|
|
knxMediumTypes = {
|
|
[0x01]="reserved",
|
|
[0x02]="KNX TP1",
|
|
[0x04]="KNX PL110",
|
|
[0x08]="reserved",
|
|
[0x10]="KNX RF",
|
|
[0x20]="KNX IP"
|
|
}
|
|
|
|
--- Returns a raw knx request
|
|
-- @param service KNX service type of the request
|
|
-- @param ip_address IP address of the sending host
|
|
-- @param port Port where gateways should respond to
|
|
query = function(service, ip_address, port)
|
|
return string.pack(">BB I2 I2 BB I4 I2",
|
|
0x06, -- Header length
|
|
0x10, -- Protocol version
|
|
service, -- Service type
|
|
0x000e, -- Total length
|
|
0x08, -- Structure length
|
|
0x01, -- Host protocol
|
|
ipOps.todword(ip_address),
|
|
port
|
|
)
|
|
end
|
|
|
|
--- Parse a KNX address from raw bytes
|
|
-- @param addr Unpacked 2 bytes
|
|
-- @return KNX address in dotted-decimal format
|
|
parseKnxAddress = function(addr)
|
|
local a = (addr & 0xf000) >> 12
|
|
local b = (addr & 0x0f00) >> 8
|
|
local c = addr & 0xff
|
|
return a..'.'..b..'.'..c
|
|
end
|
|
|
|
--- Parse a KNX header
|
|
-- @param knxMessage A KNX message packet as a string
|
|
-- @return knx_header_length, or nil on error
|
|
-- @return knx_protocol_version, or error message
|
|
-- @return knx_service_type
|
|
-- @return knx_total_length
|
|
-- @return pos The position just after the header
|
|
parseHeader = function(knxMessage)
|
|
if #knxMessage < 6 then
|
|
return nil, "Message too short for KNX header"
|
|
end
|
|
local knx_header_length, knx_protocol_version, knx_service_type, knx_total_length, pos = string.unpack(">BB I2 I2", knxMessage)
|
|
|
|
-- TODO: Should this be 'or' instead of 'and'?
|
|
if knx_header_length ~= 0x06 and knx_protocol_version ~= 0x10 and knx_service_type ~= 0x0204 then
|
|
return nil, "Unknown KNX header format"
|
|
end
|
|
|
|
return knx_header_length, knx_protocol_version, knx_service_type, knx_total_length, pos
|
|
end
|
|
|
|
return _ENV
|