Attention is currently required from: flichtenheld, plaisthos, ralf_lici, stipa.
Hello flichtenheld, plaisthos, ralf_lici,
I'd like you to reexamine a change. Please visit
http://gerrit.openvpn.net/c/openvpn/+/1745?usp=email
to look at the new patch set (#20).
Change subject: oob: Add client probe reply parser
......................................................................
oob: Add client probe reply parser
Add oob_probe_reply_find(), the client-side counterpart of
oob_probe_request_find(): it scans a received OOB message for the probe
reply TLV, skipping other and future TLV types that are marked
optional. The reply's request_id names the probe it answers, with
which the client matches the reply to its probe.
Exercised by unit tests; the client probe path calls it in a follow-up.
Change-Id: If04ce09d4c353f5384c0c48f48f63e05869a373f
Signed-off-by: Lev Stipakov <[email protected]>
---
M src/openvpn/oob.c
M src/openvpn/oob.h
M tests/unit_tests/openvpn/test_oob.c
3 files changed, 123 insertions(+), 0 deletions(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/45/1745/20
diff --git a/src/openvpn/oob.c b/src/openvpn/oob.c
index 954694a..5bd3ea6 100644
--- a/src/openvpn/oob.c
+++ b/src/openvpn/oob.c
@@ -93,6 +93,14 @@
}
bool
+oob_probe_reply_find(struct buffer *payload, struct oob_probe_reply *reply)
+{
+ struct buffer value;
+ return ctrl_msg_find_tlv(payload, TLV_TYPE_PROBE_REPLY, &value)
+ && oob_probe_reply_read(&value, reply);
+}
+
+bool
oob_timestamp_in_window(uint64_t probe_ts, uint64_t now, uint64_t window_secs)
{
uint64_t diff = (now > probe_ts) ? (now - probe_ts) : (probe_ts - now);
diff --git a/src/openvpn/oob.h b/src/openvpn/oob.h
index 95b3afc..a388e61 100644
--- a/src/openvpn/oob.h
+++ b/src/openvpn/oob.h
@@ -111,6 +111,16 @@
bool oob_probe_request_find(struct buffer *payload, struct oob_probe_request
*req);
/**
+ * Scan the payload of a received OOB message for the probe reply TLV; the
+ * client-side counterpart of oob_probe_request_find().
+ *
+ * @param payload buffer positioned at the start of the OOB message payload
+ * @param reply filled with the parsed probe reply on success
+ * @return true if a well-formed probe reply was found, false otherwise
+ */
+bool oob_probe_reply_find(struct buffer *payload, struct oob_probe_reply
*reply);
+
+/**
* Check whether a probe timestamp is within an acceptable window around the
* current time. Used to cheaply drop replayed or implausibly-timed probes
* before doing any further work (see the probe request timestamp rationale
diff --git a/tests/unit_tests/openvpn/test_oob.c
b/tests/unit_tests/openvpn/test_oob.c
index 8af595d..f1e64b7 100644
--- a/tests/unit_tests/openvpn/test_oob.c
+++ b/tests/unit_tests/openvpn/test_oob.c
@@ -527,6 +527,106 @@
gc_free(&gc);
}
+/* A payload of just a probe reply is found by the client scan, with all
+ * fields surviving. */
+static void
+test_probe_reply_find(void **state)
+{
+ struct gc_arena gc = gc_new();
+ struct buffer buf = alloc_buf_gc(128, &gc);
+
+ struct oob_probe_reply in = {
+ .request_id = 7,
+ .priority = 5,
+ .weight = 50,
+ .max_latency_diff = 25,
+ .connect_lifetime = 120,
+ .flags = 1,
+ };
+ assert_true(oob_probe_reply_write(&buf, &in));
+
+ struct oob_probe_reply out = { 0 };
+ assert_true(oob_probe_reply_find(&buf, &out));
+ assert_int_equal(out.request_id, in.request_id);
+ assert_int_equal(out.priority, in.priority);
+ assert_int_equal(out.weight, in.weight);
+ assert_int_equal(out.max_latency_diff, in.max_latency_diff);
+ assert_int_equal(out.connect_lifetime, in.connect_lifetime);
+ assert_int_equal(out.flags, in.flags);
+
+ gc_free(&gc);
+}
+
+/* TLVs other than the probe reply are skipped. */
+static void
+test_probe_reply_find_skips_unknown(void **state)
+{
+ struct gc_arena gc = gc_new();
+ struct buffer buf = alloc_buf_gc(128, &gc);
+
+ assert_true(ctrl_msg_tlv_write_header(&buf, 0x7ff, true, 4));
+ assert_true(buf_write_u32(&buf, 0xabad1dea));
+ struct oob_probe_reply in = { .priority = 7 };
+ assert_true(oob_probe_reply_write(&buf, &in));
+
+ struct oob_probe_reply out = { 0 };
+ assert_true(oob_probe_reply_find(&buf, &out));
+ assert_int_equal(out.priority, 7);
+
+ gc_free(&gc);
+}
+
+/* As on the probe side, a mandatory TLV we do not understand -- here trailing
+ * the probe reply -- invalidates the reply. */
+static void
+test_probe_reply_find_rejects_unknown_mandatory(void **state)
+{
+ struct gc_arena gc = gc_new();
+ struct buffer buf = alloc_buf_gc(128, &gc);
+
+ struct oob_probe_reply in = { .priority = 7 };
+ assert_true(oob_probe_reply_write(&buf, &in));
+ assert_true(ctrl_msg_tlv_write_header(&buf, 0x7ff, false, 4));
+ assert_true(buf_write_u32(&buf, 0xabad1dea));
+
+ struct oob_probe_reply out = { 0 };
+ assert_false(oob_probe_reply_find(&buf, &out));
+
+ gc_free(&gc);
+}
+
+/* A payload with no probe reply is rejected. */
+static void
+test_probe_reply_find_missing(void **state)
+{
+ struct gc_arena gc = gc_new();
+ struct buffer buf = alloc_buf_gc(128, &gc);
+
+ assert_true(ctrl_msg_tlv_write_header(&buf, 0x7ff, true, 4));
+ assert_true(buf_write_u32(&buf, 0));
+
+ struct oob_probe_reply out = { 0 };
+ assert_false(oob_probe_reply_find(&buf, &out));
+
+ gc_free(&gc);
+}
+
+/* Likewise, a payload carrying a probe request instead holds no probe reply.
*/
+static void
+test_probe_reply_find_request_tlv(void **state)
+{
+ struct gc_arena gc = gc_new();
+ struct buffer buf = alloc_buf_gc(128, &gc);
+
+ const struct oob_probe_request in = { .request_id = 7 };
+ assert_true(oob_probe_request_write(&buf, &in));
+
+ struct oob_probe_reply out = { 0 };
+ assert_false(oob_probe_reply_find(&buf, &out));
+
+ gc_free(&gc);
+}
+
/* The OOB tests run as a second group of pkt_testdriver; see test_pkt.c. */
int
run_oob_tests(void)
@@ -552,6 +652,11 @@
cmocka_unit_test(test_probe_request_check_valid),
cmocka_unit_test(test_probe_request_check_stale),
cmocka_unit_test(test_probe_request_check_no_request),
+ cmocka_unit_test(test_probe_reply_find),
+ cmocka_unit_test(test_probe_reply_find_skips_unknown),
+ cmocka_unit_test(test_probe_reply_find_rejects_unknown_mandatory),
+ cmocka_unit_test(test_probe_reply_find_missing),
+ cmocka_unit_test(test_probe_reply_find_request_tlv),
};
return cmocka_run_group_tests_name("oob tests", tests, NULL, NULL);
--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1745?usp=email
To unsubscribe, or for help writing mail filters, visit
http://gerrit.openvpn.net/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: If04ce09d4c353f5384c0c48f48f63e05869a373f
Gerrit-Change-Number: 1745
Gerrit-PatchSet: 20
Gerrit-Owner: stipa <[email protected]>
Gerrit-Reviewer: flichtenheld <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-Reviewer: ralf_lici <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: ralf_lici <[email protected]>
Gerrit-Attention: stipa <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
Gerrit-Attention: flichtenheld <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel