Add secure transport and OAM router runtime implementations
- Implement secure transport mechanisms in `gateway_knx_secure_transport.cpp` for handling secure sessions, including AES encryption, session key generation, and secure packet wrapping and unwrapping. - Introduce `OamRouterRuntime` in `oam_router_runtime.cpp` to manage OAM router identity, individual addresses, and tunnel frame handling. - Enhance secure session management with functions for session allocation, authentication, and secure packet processing. - Ensure compatibility with existing KNXnet/IP protocols while adding support for secure communications. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -8,6 +8,9 @@ void GatewayKnxTpIpRouter::selectOpenKnxNetworkInterface(const sockaddr_in& remo
|
||||
if (ets_device_ != nullptr) {
|
||||
ets_device_->setNetworkInterface(netif.has_value() ? netif->netif : nullptr);
|
||||
}
|
||||
if (oam_router_ != nullptr) {
|
||||
oam_router_->setNetworkInterface(netif.has_value() ? netif->netif : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool GatewayKnxTpIpRouter::handleOpenKnxTunnelFrame(const uint8_t* data, size_t len,
|
||||
@@ -15,6 +18,20 @@ bool GatewayKnxTpIpRouter::handleOpenKnxTunnelFrame(const uint8_t* data, size_t
|
||||
uint16_t response_service,
|
||||
const uint8_t* suppress_routing_echo,
|
||||
size_t suppress_routing_echo_len) {
|
||||
bool route_to_oam = response_client != nullptr && response_client->oam_router_persona;
|
||||
if (!route_to_oam && data != nullptr && len >= 2) {
|
||||
std::vector<uint8_t> frame_data(data, data + len);
|
||||
CemiFrame frame(frame_data.data(), static_cast<uint16_t>(frame_data.size()));
|
||||
if (frame.valid() && oam_router_ != nullptr &&
|
||||
MatchesOamRouterLocalIndividualAddress(frame, *oam_router_)) {
|
||||
route_to_oam = true;
|
||||
}
|
||||
}
|
||||
if (route_to_oam) {
|
||||
return handleOamRouterTunnelFrame(data, len, response_client, response_service,
|
||||
suppress_routing_echo, suppress_routing_echo_len);
|
||||
}
|
||||
|
||||
SemaphoreGuard guard(openknx_lock_);
|
||||
if (ets_device_ == nullptr) {
|
||||
return false;
|
||||
@@ -87,6 +104,82 @@ bool GatewayKnxTpIpRouter::handleOpenKnxTunnelFrame(const uint8_t* data, size_t
|
||||
return consumed;
|
||||
}
|
||||
|
||||
bool GatewayKnxTpIpRouter::handleOamRouterTunnelFrame(const uint8_t* data, size_t len,
|
||||
TunnelClient* response_client,
|
||||
uint16_t response_service,
|
||||
const uint8_t* suppress_routing_echo,
|
||||
size_t suppress_routing_echo_len) {
|
||||
SemaphoreGuard guard(openknx_lock_);
|
||||
if (oam_router_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> tunnel_confirmation;
|
||||
const bool needs_tunnel_confirmation =
|
||||
response_client != nullptr && response_client->connected &&
|
||||
response_service == kServiceTunnellingRequest &&
|
||||
BuildTunnelConfirmationFrame(data, len, &tunnel_confirmation);
|
||||
bool sent_tunnel_confirmation = false;
|
||||
const bool consumed = oam_router_->handleTunnelFrame(
|
||||
data, len,
|
||||
[this, response_client, response_service, needs_tunnel_confirmation,
|
||||
&tunnel_confirmation, &sent_tunnel_confirmation,
|
||||
suppress_routing_echo, suppress_routing_echo_len](const uint8_t* response,
|
||||
size_t response_len) {
|
||||
if (response == nullptr || response_len == 0) {
|
||||
return;
|
||||
}
|
||||
const bool routing_context =
|
||||
response_client == nullptr && response_service == kServiceRoutingIndication;
|
||||
const auto message_code = CemiMessageCode(response, response_len);
|
||||
if (routing_context && suppress_routing_echo != nullptr &&
|
||||
IsLocalRoutingEchoIndication(response, response_len, suppress_routing_echo,
|
||||
suppress_routing_echo_len)) {
|
||||
return;
|
||||
}
|
||||
if (needs_tunnel_confirmation && !sent_tunnel_confirmation &&
|
||||
message_code.has_value() && message_code.value() != L_data_con) {
|
||||
sent_tunnel_confirmation = sendCemiFrameToClient(
|
||||
*response_client, kServiceTunnellingRequest,
|
||||
tunnel_confirmation.data(), tunnel_confirmation.size());
|
||||
}
|
||||
|
||||
const uint16_t service = KnxIpServiceForCemi(response, response_len, response_service);
|
||||
if (service == kServiceDeviceConfigurationRequest) {
|
||||
if (response_client != nullptr && response_client->connected) {
|
||||
sendCemiFrameToClient(*response_client, service, response, response_len);
|
||||
} else if (routing_context) {
|
||||
sendRoutingIndication(response, response_len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (message_code.has_value() && message_code.value() == L_data_con) {
|
||||
if (routing_context) {
|
||||
return;
|
||||
}
|
||||
if (response_client != nullptr && response_client->connected) {
|
||||
sent_tunnel_confirmation =
|
||||
sendCemiFrameToClient(*response_client, service, response, response_len) ||
|
||||
sent_tunnel_confirmation;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (routing_context) {
|
||||
sendRoutingIndication(response, response_len);
|
||||
return;
|
||||
}
|
||||
if (response_client != nullptr && response_client->connected) {
|
||||
sendCemiFrameToClient(*response_client, service, response, response_len);
|
||||
return;
|
||||
}
|
||||
sendTunnelIndication(response, response_len);
|
||||
});
|
||||
if (needs_tunnel_confirmation && consumed && !sent_tunnel_confirmation) {
|
||||
sendCemiFrameToClient(*response_client, kServiceTunnellingRequest,
|
||||
tunnel_confirmation.data(), tunnel_confirmation.size());
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
bool GatewayKnxTpIpRouter::transmitOpenKnxTpFrame(const uint8_t* data, size_t len) {
|
||||
SemaphoreGuard guard(openknx_lock_);
|
||||
if (ets_device_ == nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user