1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
--- 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
|