mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-02 22:03:01 +02:00
To be able to maintain our own set of patches on top rousette, a kkit branch have been set up with a reduced set of backported fixes. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
138 lines
4.8 KiB
Diff
138 lines
4.8 KiB
Diff
From 027a47ac3ff6c369caab7c007a5a171a68270829 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <tomas.pecka@cesnet.cz>
|
|
Date: Fri, 13 Jun 2025 10:47:55 +0200
|
|
Subject: [PATCH 02/13] restconf: prevent throwing exception in
|
|
withRestconfExceptions wrapper
|
|
Organization: Wires
|
|
|
|
In case the catch block of withRestconfExceptions is reached and an
|
|
exception is thrown, rousette will start behaving in a strange way
|
|
where no new connections are accepted and already connected clients are
|
|
not receiving the content [1].
|
|
|
|
This patch prevents throwing the exception that would slip through our
|
|
catch handlers.
|
|
An uncaught exception is a problem though, so expect a followup patch to
|
|
handle such situations.
|
|
|
|
[1] https://github.com/CESNET/rousette/issues/19
|
|
|
|
Bug: https://github.com/CESNET/rousette/issues/19
|
|
Change-Id: Ifbd74b9bdc0ca66c4e5449a7673ef2f12ae9215e
|
|
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
|
---
|
|
src/restconf/Server.cpp | 2 +-
|
|
tests/restconf-plain-patch.cpp | 24 ++++++++++++++++++++++++
|
|
tests/restconf-reading.cpp | 3 +++
|
|
tests/yang/example.yang | 19 +++++++++++++++++++
|
|
4 files changed, 47 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/restconf/Server.cpp b/src/restconf/Server.cpp
|
|
index 9821495..1c2123e 100644
|
|
--- a/src/restconf/Server.cpp
|
|
+++ b/src/restconf/Server.cpp
|
|
@@ -350,7 +350,7 @@ constexpr auto withRestconfExceptions(T func, U rejectWithError)
|
|
} else if (e.code() == sysrepo::ErrorCode::ItemAlreadyExists) {
|
|
rejectWithError(requestCtx->sess.getContext(), requestCtx->dataFormat.response, requestCtx->req, requestCtx->res, 409, "application", "resource-denied", "Resource already exists.", std::nullopt);
|
|
} else if (e.code() == sysrepo::ErrorCode::ValidationFailed) {
|
|
- bool isAction = requestCtx->sess.getContext().findPath(requestCtx->restconfRequest.path).nodeType() == libyang::NodeType::Action;
|
|
+ bool isAction = requestCtx->restconfRequest.path != "/" && requestCtx->sess.getContext().findPath(requestCtx->restconfRequest.path).nodeType() == libyang::NodeType::Action;
|
|
/*
|
|
* FIXME: This happens on invalid input data (e.g., missing mandatory nodes) or missing action data node.
|
|
* The former (invalid input data) should probably be validated by libyang's parseOp but it only parses.
|
|
diff --git a/tests/restconf-plain-patch.cpp b/tests/restconf-plain-patch.cpp
|
|
index b550f54..34813d1 100644
|
|
--- a/tests/restconf-plain-patch.cpp
|
|
+++ b/tests/restconf-plain-patch.cpp
|
|
@@ -179,5 +179,29 @@ TEST_CASE("Plain patch")
|
|
]
|
|
}
|
|
}
|
|
+)"});
|
|
+
|
|
+ REQUIRE(patch(RESTCONF_ROOT_DS("running"), {AUTH_ROOT, CONTENT_TYPE_JSON}, R"({
|
|
+ "example:channel-plan": {
|
|
+ "channel": [
|
|
+ {
|
|
+ "name": "coriant",
|
|
+ "lower-frequency": 199999999,
|
|
+ "upper-frequency": 191500000
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+}
|
|
+)") == Response{400, jsonHeaders, R"({
|
|
+ "ietf-restconf:errors": {
|
|
+ "error": [
|
|
+ {
|
|
+ "error-type": "application",
|
|
+ "error-tag": "operation-failed",
|
|
+ "error-message": "Validation failed. Invalid input data."
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+}
|
|
)"});
|
|
}
|
|
diff --git a/tests/restconf-reading.cpp b/tests/restconf-reading.cpp
|
|
index f87c4f5..4f0d2ee 100644
|
|
--- a/tests/restconf-reading.cpp
|
|
+++ b/tests/restconf-reading.cpp
|
|
@@ -62,6 +62,7 @@ TEST_CASE("reading data")
|
|
// this relies on a NACM rule for anonymous access that filters out "a lot of stuff"
|
|
REQUIRE(get(RESTCONF_DATA_ROOT, {}) == Response{200, jsonHeaders, R"({
|
|
"example:top-level-leaf": "moo",
|
|
+ "example:channel-plan": {},
|
|
"example:tlc": {},
|
|
"example:a": {
|
|
"b": {
|
|
@@ -119,6 +120,7 @@ TEST_CASE("reading data")
|
|
|
|
REQUIRE(get(RESTCONF_ROOT_DS("operational"), {}) == Response{200, jsonHeaders, R"({
|
|
"example:top-level-leaf": "moo",
|
|
+ "example:channel-plan": {},
|
|
"example:tlc": {},
|
|
"example:a": {
|
|
"b": {
|
|
@@ -176,6 +178,7 @@ TEST_CASE("reading data")
|
|
|
|
REQUIRE(get(RESTCONF_ROOT_DS("running"), {}) == Response{200, jsonHeaders, R"({
|
|
"example:top-level-leaf": "moo",
|
|
+ "example:channel-plan": {},
|
|
"example:tlc": {},
|
|
"example:a": {
|
|
"b": {
|
|
diff --git a/tests/yang/example.yang b/tests/yang/example.yang
|
|
index 5d586a0..1cd12e3 100644
|
|
--- a/tests/yang/example.yang
|
|
+++ b/tests/yang/example.yang
|
|
@@ -27,6 +27,25 @@ module example {
|
|
}
|
|
leaf-list top-level-leaf-list { type int32; }
|
|
|
|
+ container channel-plan {
|
|
+ list channel {
|
|
+ key "name";
|
|
+ leaf name { type string; }
|
|
+ leaf lower-frequency {
|
|
+ type int32;
|
|
+ units "Hz";
|
|
+ }
|
|
+ leaf upper-frequency {
|
|
+ type int32;
|
|
+ units "Hz";
|
|
+ }
|
|
+
|
|
+ must "lower-frequency < upper-frequency" {
|
|
+ description "The lower frequency must be less than the upper frequency.";
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
container tlc {
|
|
if-feature f1;
|
|
list list {
|
|
--
|
|
2.43.0
|
|
|