[PATCH] strv: Add l_strv_eq
by Andrew Zaborowski
---
ell/ell.sym | 1 +
ell/strv.c | 20 ++++++++++++++++++++
ell/strv.h | 1 +
3 files changed, 22 insertions(+)
diff --git a/ell/ell.sym b/ell/ell.sym
index 9fcf334..10865af 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -40,6 +40,7 @@ global:
l_strv_append_printf;
l_strv_append_vprintf;
l_strv_copy;
+ l_strv_eq;
/* utf8 */
l_ascii_table;
l_utf8_get_codepoint;
diff --git a/ell/strv.c b/ell/strv.c
index 3df47be..1343519 100644
--- a/ell/strv.c
+++ b/ell/strv.c
@@ -359,3 +359,23 @@ LIB_EXPORT char **l_strv_copy(char **str_array)
return copy;
}
+
+/**
+ * l_strv_eq:
+ * @a: a %NULL terminated array of strings or %NULL
+ * @b: another %NULL terminated array of strings or %NULL
+ *
+ * Returns: Whether @a and @b's contents are identical, including the
+ * order, or @a and @b are both %NULL.
+ */
+LIB_EXPORT bool l_strv_eq(char **a, char **b)
+{
+ if (!a || !b)
+ return a == b;
+
+ for (; *a; a++, b++)
+ if (!*b || strcmp(*a, *b))
+ return false;
+
+ return !*b;
+}
diff --git a/ell/strv.h b/ell/strv.h
index e673fec..db15cc7 100644
--- a/ell/strv.h
+++ b/ell/strv.h
@@ -46,6 +46,7 @@ char **l_strv_append_vprintf(char **str_array, const char *format,
va_list args)
__attribute__((format(printf, 2, 0)));
char **l_strv_copy(char **str_array);
+bool l_strv_eq(char **a, char **b);
#ifdef __cplusplus
}
--
2.30.2
3 months, 3 weeks
[PATCH v2] utf8: fixed bit shift larger than type size
by James Prestwood
The C standard requires the bit shift result value width to be greater
than or equal to the number of bits being shifted, otherwise the behavior
is undefined. In this case str[0] was being cast to an unsigned char
(1 byte) but being shifted 24 bits. This resulted, on some compilers,
with a runtime error:
runtime error: left shift of 255 by 24 places cannot be represented in type 'int'
Casting str[0] to an unsigned int satisfies the width requirements
for this bit shift.
Fixes: 9843abcd84bc ("utf8: cast to avoid left shift of negative value (ubsan)")
---
ell/utf8.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
v2:
* Added Fixes tag
diff --git a/ell/utf8.c b/ell/utf8.c
index 84ab774..ceda1de 100644
--- a/ell/utf8.c
+++ b/ell/utf8.c
@@ -98,7 +98,7 @@ LIB_EXPORT int l_utf8_get_codepoint(const char *str, size_t len, wchar_t *cp)
return 1;
}
- expect_bytes = __builtin_clz(~((unsigned char)str[0] << 24));
+ expect_bytes = __builtin_clz(~((unsigned int)str[0] << 24));
if (expect_bytes < 2 || expect_bytes > 4)
goto error;
--
2.34.1
4 months
[PATCH] utf8: fixed bit shift larger than type size
by James Prestwood
The C standard requires the bit shift result value width to be greater
than or equal to the number of bits being shifted, otherwise the behavior
is undefined. In this case str[0] was being cast to an unsigned char
(1 byte) but being shifted 24 bits. This resulted, on some compilers,
with a runtime error:
runtime error: left shift of 255 by 24 places cannot be represented in type 'int'
Casting str[0] to an unsigned int satisfies the width requirements
for this bit shift.
---
ell/utf8.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ell/utf8.c b/ell/utf8.c
index 84ab774..ceda1de 100644
--- a/ell/utf8.c
+++ b/ell/utf8.c
@@ -98,7 +98,7 @@ LIB_EXPORT int l_utf8_get_codepoint(const char *str, size_t len, wchar_t *cp)
return 1;
}
- expect_bytes = __builtin_clz(~((unsigned char)str[0] << 24));
+ expect_bytes = __builtin_clz(~((unsigned int)str[0] << 24));
if (expect_bytes < 2 || expect_bytes > 4)
goto error;
--
2.34.1
4 months
[PATCH v2 1/2] base64: refactor l_base64_decode and validate bytes consumed
by James Prestwood
The way the base64 data was being validated was accurate, but included a
second loop to iterate the padding. There was nothing wrong with this but
for more concise/readable code the padding can be calculated and validated
all after the first loop by incrementing pad_len when '=' is found rather
than breaking out. The valid base64 character check did need a slight
modification to also check that pad_len has not been incremented, which
ensures there is no data after the padding (prior this was done by the
second, pad checking, loop).
Then, after the loop, pad_len has been calculated and can be checked against
what was expected based on the valid base64 characters found.
This refactoring also makes checking the bytes consumed much easier since
the first loop iterates until the very end of the base64 data (including
padding).
---
ell/base64.c | 41 ++++++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 19 deletions(-)
v2:
* Fix issue in calculating the end of the base64 data (caused test-pem to
fail). This was because whitespace was not taken into account which
could exist between the base64 and padding. Instead the end of the
base64 data is now saved when the first pad byte is found. This allows
the second loop to use this as its end condition.
diff --git a/ell/base64.c b/ell/base64.c
index e430470..747d4d5 100644
--- a/ell/base64.c
+++ b/ell/base64.c
@@ -27,56 +27,59 @@
#include "utf8.h"
#include "base64.h"
#include "private.h"
+#include "useful.h"
+
+#include <stdio.h>
LIB_EXPORT uint8_t *l_base64_decode(const char *in, size_t in_len,
size_t *n_written)
{
const char *ptr, *in_end = in + in_len;
+ const char *base64_end = NULL;
uint8_t *out_buf, *out;
- int base64_len = 0, pad_len;
+ int base64_len = 0, pad_len = 0;
uint16_t reg = 0;
- for (ptr = in; ptr < in_end; ptr++)
+ for (ptr = in; ptr < in_end; ptr++) {
if (l_ascii_isspace(*ptr))
/* Whitespace */
continue;
- else if (*ptr == '=')
+ else if (*ptr == '=') {
/* Final padding */
- break;
- else if (l_ascii_isalnum(*ptr) || *ptr == '+' || *ptr == '/')
+ if (!pad_len)
+ base64_end = ptr;
+
+ pad_len++;
+ } else if (!pad_len && (l_ascii_isalnum(*ptr) || *ptr == '+' ||
+ *ptr == '/'))
/* Base64 character */
base64_len++;
else
/* Bad character */
return NULL;
+ }
- in_end = ptr;
+ if (ptr != in_end)
+ return NULL;
if ((base64_len & 3) == 1)
/* Invalid length */
return NULL;
- pad_len = (4 - base64_len) & 3;
- for (; ptr < in + in_len && pad_len; ptr++)
- if (l_ascii_isspace(*ptr))
- /* Whitespace */
- continue;
- else if (*ptr == '=')
- /* Final padding */
- pad_len--;
- else
- /* Bad character */
- return NULL;
- if (pad_len)
+ if (pad_len != align_len(base64_len, 4) - base64_len)
return NULL;
+ /* No padding */
+ if (!base64_end)
+ base64_end = ptr;
+
*n_written = base64_len * 3 / 4;
out_buf = l_malloc(*n_written);
out = out_buf;
base64_len = 0;
- for (ptr = in; ptr < in_end; ptr++) {
+ for (ptr = in; ptr < base64_end; ptr++) {
if (l_ascii_isspace(*ptr))
/* Whitespace */
continue;
--
2.34.1
4 months, 1 week
[PATCH] base64: refactor l_base64_decode and validate bytes consumed
by James Prestwood
The way the base64 data was being validated was accurate, but included a
second loop to iterate the padding. There was nothing wrong with this but
for more concise/readable code the padding can be calculated and validated
all after the first loop by incrementing pad_len when '=' is found rather
than breaking out. The valid base64 character check did need a slight
modification to also check that pad_len has not been incremented, which
ensures there is no data after the padding (prior this was done by the
second, pad checking, loop).
Then, after the loop, pad_len has been calculated and can be checked against
what was expected based on the valid base64 characters found.
This refactoring also makes checking the bytes consumed much easier since
the first loop iterates until the very end of the base64 data (including
padding).
---
ell/base64.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/ell/base64.c b/ell/base64.c
index e430470..340550f 100644
--- a/ell/base64.c
+++ b/ell/base64.c
@@ -33,7 +33,7 @@ LIB_EXPORT uint8_t *l_base64_decode(const char *in, size_t in_len,
{
const char *ptr, *in_end = in + in_len;
uint8_t *out_buf, *out;
- int base64_len = 0, pad_len;
+ int base64_len = 0, pad_len = 0;
uint16_t reg = 0;
for (ptr = in; ptr < in_end; ptr++)
@@ -42,32 +42,25 @@ LIB_EXPORT uint8_t *l_base64_decode(const char *in, size_t in_len,
continue;
else if (*ptr == '=')
/* Final padding */
- break;
- else if (l_ascii_isalnum(*ptr) || *ptr == '+' || *ptr == '/')
+ pad_len++;
+ else if (!pad_len && (l_ascii_isalnum(*ptr) || *ptr == '+' ||
+ *ptr == '/'))
/* Base64 character */
base64_len++;
else
/* Bad character */
return NULL;
- in_end = ptr;
+ if (ptr != in_end)
+ return NULL;
+
+ in_end = ptr - pad_len;
if ((base64_len & 3) == 1)
/* Invalid length */
return NULL;
- pad_len = (4 - base64_len) & 3;
- for (; ptr < in + in_len && pad_len; ptr++)
- if (l_ascii_isspace(*ptr))
- /* Whitespace */
- continue;
- else if (*ptr == '=')
- /* Final padding */
- pad_len--;
- else
- /* Bad character */
- return NULL;
- if (pad_len)
+ if (pad_len != ((4 - base64_len) & 3))
return NULL;
*n_written = base64_len * 3 / 4;
--
2.34.1
4 months, 1 week
[PATCH] unit: add compressed point test
by James Prestwood
This tests the 4 different ways a compressed point can be computed:
The two compressed point types with and without subtraction.
---
unit/test-ecc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/unit/test-ecc.c b/unit/test-ecc.c
index 1cd8b22..21f73f1 100644
--- a/unit/test-ecc.c
+++ b/unit/test-ecc.c
@@ -366,6 +366,66 @@ static void run_test_zero_or_one(const void *arg)
assert(!_vli_is_zero_or_one(_2, L_ECC_MAX_DIGITS));
}
+struct compressed_point_data {
+ char *x;
+ char *exp_y;
+ enum l_ecc_point_type type;
+};
+
+static struct compressed_point_data compressed_tests[] = {
+ {
+ /* BIT1, subtraction performed */
+ .x = "19b3fec1c000a888ee9c44272e4d7317e6e36577fc9d53e1edfb4e296b0b7ce1",
+ .exp_y = "a8f9efd0ab526cd930870779621f4e9a53d4e78887ac9f4ed45ff75ded32b158",
+ .type = L_ECC_POINT_TYPE_COMPRESSED_BIT1,
+ },
+ {
+ /* BIT1, no subtraction */
+ .x = "958df5997362a9695ad73938c86be34a4730da877eccaaf8b189e73ff20e67c3",
+ .exp_y = "1042f37262ded34d8424c1728a1ed23a726645b71db30a38f2932001a2027f46",
+ .type = L_ECC_POINT_TYPE_COMPRESSED_BIT1,
+ },
+ {
+ /* BIT0, subtraction performed */
+ .x = "069bd56634454ca76e7ba434244137509141cbbf532586c6b36e9b5be8a2cc34",
+ .exp_y = "f4f34d46e4bdc1473fec4b4c8724f349375a8a602f5e83c260d6724e64ec7e99",
+ .type = L_ECC_POINT_TYPE_COMPRESSED_BIT0,
+ },
+ {
+ /* BIT0, no subtraction */
+ .x = "8cade296a68e0c40bcf45a049f1993263bdc8524825e2be44b14ce114e475df0",
+ .exp_y = "94ed7d09b2a0e95d8df993eaf81eb64d5ff734d01da57e53b2e0277199bc5897",
+ .type = L_ECC_POINT_TYPE_COMPRESSED_BIT0,
+ },
+};
+
+static void run_test_compressed_points(const void *arg)
+{
+ unsigned int i;
+
+ for (i = 0; i < L_ARRAY_SIZE(compressed_tests); i++) {
+ const struct l_ecc_curve *curve = l_ecc_curve_from_ike_group(19);
+ struct compressed_point_data *data = &compressed_tests[i];
+ uint64_t x[L_ECC_MAX_DIGITS];
+ uint64_t y[L_ECC_MAX_DIGITS];
+ uint64_t exp_y[L_ECC_MAX_DIGITS];
+ size_t bytes = l_ecc_curve_get_scalar_bytes(curve);
+ struct l_ecc_point *p;
+
+ HEX2BUF(data->x, x);
+ HEX2BUF(data->exp_y, exp_y);
+
+ p = l_ecc_point_from_data(curve, data->type, x, bytes);
+ assert(p);
+
+ l_ecc_point_get_y(p, y, bytes);
+
+ assert(!memcmp(exp_y, y, bytes));
+
+ l_ecc_point_free(p);
+ }
+}
+
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
@@ -387,6 +447,7 @@ int main(int argc, char *argv[])
l_test_add("ECC reduce test", run_test_reduce, NULL);
l_test_add("ECC zero or one test", run_test_zero_or_one, NULL);
+ l_test_add("ECC compressed points", run_test_compressed_points, NULL);
return l_test_run();
}
--
2.34.1
4 months, 1 week
[PATCH 1/6] rtnl: Track expiry times instead of lifetimes
by Andrew Zaborowski
Internally within rtnl.c store expiry times of addresses and routes
instead of their lifetime periods so that at any time the current
lifetime left can be returned. This is an incompatible API change to
the lifetime getters and setters as they now take a reference_time
parameter, which in the setter case should normally be the timestamp of
when the address or route was received from DHCP. These setters and
getters don't seem to have been used outside of ell.
---
ell/dhcp.c | 3 ++-
ell/dhcp6.c | 3 ++-
ell/rtnl.c | 71 ++++++++++++++++++++++++++++++++++-------------------
ell/rtnl.h | 15 +++++++----
4 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/ell/dhcp.c b/ell/dhcp.c
index e2d18fc..89f1306 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -680,6 +680,7 @@ static int dhcp_client_receive_ack(struct l_dhcp_client *client,
struct dhcp_message_iter iter;
struct l_dhcp_lease *lease;
int r;
+ uint64_t now = l_time_now();
CLIENT_DEBUG("");
@@ -734,7 +735,7 @@ static int dhcp_client_receive_ack(struct l_dhcp_client *client,
a = l_rtnl_address_new(ip, prefix_len);
l_rtnl_address_set_noprefixroute(a, true);
- l_rtnl_address_set_lifetimes(a, l, l);
+ l_rtnl_address_set_lifetimes(a, l, l, now);
l_rtnl_address_set_broadcast(a, broadcast);
client->rtnl_add_cmdid =
diff --git a/ell/dhcp6.c b/ell/dhcp6.c
index 40c6f3a..0a660d6 100644
--- a/ell/dhcp6.c
+++ b/ell/dhcp6.c
@@ -967,6 +967,7 @@ static void dhcp6_client_setup_lease(struct l_dhcp6_client *client)
uint32_t t1 = _dhcp6_lease_get_t1(client->lease);
uint32_t t2 = _dhcp6_lease_get_t2(client->lease);
enum l_dhcp6_client_event event;
+ uint64_t now = l_time_now();
client->lease_start_t = l_time_now();
@@ -1007,7 +1008,7 @@ static void dhcp6_client_setup_lease(struct l_dhcp6_client *client)
a = l_rtnl_address_new(ip, prefix_len);
l_rtnl_address_set_noprefixroute(a, true);
- l_rtnl_address_set_lifetimes(a, p, v);
+ l_rtnl_address_set_lifetimes(a, p, v, now);
client->rtnl_add_cmdid =
l_rtnl_ifaddr_add(client->rtnl, client->ifindex, a,
diff --git a/ell/rtnl.c b/ell/rtnl.c
index 4a1a248..dda27cf 100644
--- a/ell/rtnl.c
+++ b/ell/rtnl.c
@@ -38,6 +38,7 @@
#include "netlink.h"
#include "log.h"
#include "util.h"
+#include "time.h"
#include "rtnl.h"
#include "private.h"
@@ -51,8 +52,8 @@ struct l_rtnl_address {
};
struct in_addr broadcast;
char label[IFNAMSIZ];
- uint32_t preferred_lifetime;
- uint32_t valid_lifetime;
+ uint64_t preferred_expiry_time;
+ uint64_t valid_expiry_time;
uint32_t flags;
};
@@ -108,8 +109,8 @@ static inline void _rtnl_address_init(struct l_rtnl_address *addr,
addr->scope = RT_SCOPE_UNIVERSE;
addr->flags = IFA_F_PERMANENT;
memset(addr->label, 0, sizeof(addr->label));
- addr->preferred_lifetime = 0;
- addr->valid_lifetime = 0;
+ addr->preferred_expiry_time = 0;
+ addr->valid_expiry_time = 0;
l_rtnl_address_set_broadcast(addr, NULL);
}
@@ -255,32 +256,40 @@ LIB_EXPORT bool l_rtnl_address_set_noprefixroute(struct l_rtnl_address *addr,
}
LIB_EXPORT uint32_t l_rtnl_address_get_valid_lifetime(
- const struct l_rtnl_address *addr)
+ const struct l_rtnl_address *addr,
+ uint64_t reference_time)
{
if (unlikely(!addr))
return false;
- return addr->valid_lifetime;
+ return addr->valid_expiry_time > reference_time ?
+ l_time_to_secs(addr->valid_expiry_time - reference_time) : 0;
}
LIB_EXPORT uint32_t l_rtnl_address_get_preferred_lifetime(
- const struct l_rtnl_address *addr)
+ const struct l_rtnl_address *addr,
+ uint64_t reference_time)
{
if (unlikely(!addr))
return false;
- return addr->preferred_lifetime;
+ return addr->preferred_expiry_time > reference_time ?
+ l_time_to_secs(addr->preferred_expiry_time - reference_time) :
+ 0;
}
LIB_EXPORT bool l_rtnl_address_set_lifetimes(struct l_rtnl_address *addr,
uint32_t preferred_lifetime,
- uint32_t valid_lifetime)
+ uint32_t valid_lifetime,
+ uint64_t reference_time)
{
if (unlikely(!addr))
return false;
- addr->preferred_lifetime = preferred_lifetime;
- addr->valid_lifetime = valid_lifetime;
+ addr->preferred_expiry_time = reference_time +
+ preferred_lifetime * L_USEC_PER_SEC;
+ addr->valid_expiry_time = reference_time +
+ valid_lifetime * L_USEC_PER_SEC;
return true;
}
@@ -312,7 +321,7 @@ struct l_rtnl_route {
struct in6_addr in6_addr;
struct in_addr in_addr;
} prefsrc;
- uint32_t lifetime;
+ uint64_t expiry_time;
uint32_t mtu;
uint32_t priority;
uint8_t preference;
@@ -332,7 +341,6 @@ LIB_EXPORT struct l_rtnl_route *l_rtnl_route_new_gateway(const char *gw)
rt->family = family;
rt->scope = RT_SCOPE_UNIVERSE;
rt->protocol = RTPROT_UNSPEC;
- rt->lifetime = 0xffffffff;
if (family == AF_INET6)
memcpy(&rt->gw.in6_addr, &in6_addr, sizeof(in6_addr));
@@ -365,7 +373,6 @@ LIB_EXPORT struct l_rtnl_route *l_rtnl_route_new_prefix(const char *ip,
rt = l_new(struct l_rtnl_route, 1);
rt->family = family;
rt->protocol = RTPROT_UNSPEC;
- rt->lifetime = 0xffffffff;
rt->dst_prefix_len = prefix_len;
/* IPV6 prefix routes are usually global, IPV4 are link-local */
@@ -403,20 +410,26 @@ LIB_EXPORT bool l_rtnl_route_get_gateway(const struct l_rtnl_route *rt,
out_buf);
}
-LIB_EXPORT uint32_t l_rtnl_route_get_lifetime(const struct l_rtnl_route *rt)
+LIB_EXPORT uint32_t l_rtnl_route_get_lifetime(const struct l_rtnl_route *rt,
+ uint64_t reference_time)
{
if (unlikely(!rt))
return 0;
- return rt->lifetime;
+ if (!rt->expiry_time)
+ return 0xffffffff;
+
+ return rt->expiry_time > reference_time ?
+ l_time_to_secs(rt->expiry_time - reference_time) : 0;
}
-LIB_EXPORT bool l_rtnl_route_set_lifetime(struct l_rtnl_route *rt, uint32_t lt)
+LIB_EXPORT bool l_rtnl_route_set_lifetime(struct l_rtnl_route *rt, uint32_t lt,
+ uint64_t reference_time)
{
if (unlikely(!rt))
return false;
- rt->lifetime = lt;
+ rt->expiry_time = reference_time + lt * L_USEC_PER_SEC;
return true;
}
@@ -1130,12 +1143,15 @@ static uint32_t _rtnl_ifaddr_change(struct l_netlink *rtnl, uint16_t nlmsg_type,
buf += rta_add_data(buf, IFA_LABEL,
addr->label, strlen(addr->label) + 1);
- if (addr->preferred_lifetime || addr->valid_lifetime) {
+ if (addr->preferred_expiry_time || addr->valid_expiry_time) {
struct ifa_cacheinfo cinfo;
+ uint64_t now = l_time_now();
memset(&cinfo, 0, sizeof(cinfo));
- cinfo.ifa_prefered = addr->preferred_lifetime;
- cinfo.ifa_valid = addr->valid_lifetime;
+ cinfo.ifa_prefered =
+ l_rtnl_address_get_preferred_lifetime(addr, now);
+ cinfo.ifa_valid =
+ l_rtnl_address_get_valid_lifetime(addr, now);
buf += rta_add_data(buf, IFA_CACHEINFO, &cinfo, sizeof(cinfo));
}
@@ -1156,6 +1172,7 @@ LIB_EXPORT struct l_rtnl_address *l_rtnl_ifaddr_extract(
struct rtattr *attr;
struct ifa_cacheinfo *cinfo;
struct l_rtnl_address *addr;
+ uint64_t now = l_time_now();
if (unlikely(!ifa))
return NULL;
@@ -1193,8 +1210,8 @@ LIB_EXPORT struct l_rtnl_address *l_rtnl_ifaddr_extract(
break;
case IFA_CACHEINFO:
cinfo = RTA_DATA(attr);
- addr->preferred_lifetime = cinfo->ifa_prefered;
- addr->valid_lifetime = cinfo->ifa_valid;
+ l_rtnl_address_set_lifetimes(addr, cinfo->ifa_prefered,
+ cinfo->ifa_valid, now);
break;
}
}
@@ -1288,8 +1305,12 @@ static uint32_t _rtnl_route_change(struct l_netlink *rtnl,
if (rt->preference)
rta_buf += rta_add_u8(rta_buf, RTA_PREF, rt->preference);
- if (rt->lifetime != 0xffffffff)
- rta_buf += rta_add_u32(rta_buf, RTA_EXPIRES, rt->lifetime);
+ if (rt->expiry_time) {
+ uint64_t now = l_time_now();
+
+ rta_buf += rta_add_u32(rta_buf, RTA_EXPIRES,
+ l_rtnl_route_get_lifetime(rt, now));
+ }
return l_netlink_send(rtnl, nlmsg_type, flags, rtmmsg,
rta_buf - (void *) rtmmsg, cb, user_data,
diff --git a/ell/rtnl.h b/ell/rtnl.h
index 274816c..8028d8d 100644
--- a/ell/rtnl.h
+++ b/ell/rtnl.h
@@ -54,12 +54,15 @@ const char *l_rtnl_address_get_label(const struct l_rtnl_address *addr);
bool l_rtnl_address_set_label(struct l_rtnl_address *addr, const char *label);
bool l_rtnl_address_set_noprefixroute(struct l_rtnl_address *addr,
bool noprefixroute);
-uint32_t l_rtnl_address_get_valid_lifetime(const struct l_rtnl_address *addr);
+uint32_t l_rtnl_address_get_valid_lifetime(const struct l_rtnl_address *addr,
+ uint64_t reference_time);
uint32_t l_rtnl_address_get_preferred_lifetime(
- const struct l_rtnl_address *addr);
+ const struct l_rtnl_address *addr,
+ uint64_t reference_time);
bool l_rtnl_address_set_lifetimes(struct l_rtnl_address *addr,
uint32_t preferred_lifetime,
- uint32_t valid_lifetime);
+ uint32_t valid_lifetime,
+ uint64_t reference_time);
bool l_rtnl_address_set_scope(struct l_rtnl_address *addr, uint8_t scope);
struct l_rtnl_route *l_rtnl_route_new_gateway(const char *gw);
@@ -69,8 +72,10 @@ void l_rtnl_route_free(struct l_rtnl_route *rt);
DEFINE_CLEANUP_FUNC(l_rtnl_route_free);
uint8_t l_rtnl_route_get_family(const struct l_rtnl_route *rt);
bool l_rtnl_route_get_gateway(const struct l_rtnl_route *rt, char *out_buf);
-uint32_t l_rtnl_route_get_lifetime(const struct l_rtnl_route *rt);
-bool l_rtnl_route_set_lifetime(struct l_rtnl_route *rt, uint32_t lt);
+uint32_t l_rtnl_route_get_lifetime(const struct l_rtnl_route *rt,
+ uint64_t reference_time);
+bool l_rtnl_route_set_lifetime(struct l_rtnl_route *rt, uint32_t lt,
+ uint64_t reference_time);
uint32_t l_rtnl_route_get_mtu(const struct l_rtnl_route *rt);
bool l_rtnl_route_set_mtu(struct l_rtnl_route *rt, uint32_t mtu);
uint8_t l_rtnl_route_get_preference(const struct l_rtnl_route *rt);
--
2.32.0
4 months, 2 weeks
[PATCH v3] ecc: make l_ecc_point_from_data fully constant time
by James Prestwood
This was modified earlier to be constant time but there was one
minor problem with how 'sub' was determined. That logic could short
circuit which could alter the timing. The change in timing would be
extremely small, especially compared to the previous fix making
_vli_mod_sub() execute always but in any case there would be a small
difference.
This patch uses l_secure_select_byte to select either of the two
subtraction conditions which depend on the point type.
---
ell/ecc.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/ell/ecc.c b/ell/ecc.c
index eba9aef..ad7628a 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -562,10 +562,8 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
if (!_ecc_compute_y(curve, p->y, p->x))
goto failed;
- sub = ((type == L_ECC_POINT_TYPE_COMPRESSED_BIT0 &&
- !(p->y[0] & 1)) ||
- (type == L_ECC_POINT_TYPE_COMPRESSED_BIT1 &&
- (p->y[0] & 1)));
+ sub = secure_select(type == L_ECC_POINT_TYPE_COMPRESSED_BIT0,
+ !(p->y[1] & 1), p->y[0] & 1);
_vli_mod_sub(tmp, curve->p, p->y, curve->p, curve->ndigits);
--
2.31.1
4 months, 2 weeks
[PATCH v2 1/5] settings: add l_settings_clone
by James Prestwood
Returns identical copy of settings
---
ell/ell.sym | 1 +
ell/settings.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++
ell/settings.h | 2 ++
3 files changed, 60 insertions(+)
v2:
* memdup the entire embedded_group_data structure rather than manually
copying each part individually.
diff --git a/ell/ell.sym b/ell/ell.sym
index 60c5525..827e68c 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -452,6 +452,7 @@ global:
l_ringbuf_append;
/* settings */
l_settings_new;
+ l_settings_clone;
l_settings_free;
l_settings_load_from_data;
l_settings_to_data;
diff --git a/ell/settings.c b/ell/settings.c
index 6958e12..31d23fe 100644
--- a/ell/settings.c
+++ b/ell/settings.c
@@ -116,6 +116,63 @@ LIB_EXPORT struct l_settings *l_settings_new(void)
return settings;
}
+static void copy_key_value_foreach(void *data, void *user_data)
+{
+ struct setting_data *s = data;
+ struct l_queue *settings = user_data;
+ struct setting_data *copy = l_new(struct setting_data, 1);
+
+ copy->key = l_strdup(s->key);
+ copy->value = l_strdup(s->value);
+
+ l_queue_push_head(settings, copy);
+}
+
+static void copy_group_foreach(void *data, void *user_data)
+{
+ struct group_data *group = data;
+ struct l_queue *groups = user_data;
+ struct group_data *copy = l_new(struct group_data, 1);
+
+ copy->name = l_strdup(group->name);
+ copy->settings = l_queue_new();
+
+ l_queue_push_head(groups, copy);
+
+ l_queue_foreach(group->settings, copy_key_value_foreach,
+ copy->settings);
+}
+
+static void copy_embedded_foreach(void *data, void *user_data)
+{
+ struct embedded_group_data *embedded = data;
+ struct l_queue *groups = user_data;
+ struct embedded_group_data *copy;
+
+ copy = l_memdup(embedded, sizeof(struct embedded_group_data) +
+ embedded->len + 1);
+ copy->name = l_strdup(embedded->name);
+
+ l_queue_push_tail(groups, copy);
+}
+
+LIB_EXPORT struct l_settings *l_settings_clone(
+ const struct l_settings *settings)
+{
+ struct l_settings *copy;
+
+ if (unlikely(!settings))
+ return NULL;
+
+ copy = l_settings_new();
+
+ l_queue_foreach(settings->groups, copy_group_foreach, copy->groups);
+ l_queue_foreach(settings->embedded_groups, copy_embedded_foreach,
+ copy->embedded_groups);
+
+ return copy;
+}
+
LIB_EXPORT void l_settings_free(struct l_settings *settings)
{
if (unlikely(!settings))
diff --git a/ell/settings.h b/ell/settings.h
index 9262ab9..f094ef5 100644
--- a/ell/settings.h
+++ b/ell/settings.h
@@ -37,6 +37,8 @@ typedef void (*l_settings_debug_cb_t) (const char *str, void *user_data);
typedef void (*l_settings_destroy_cb_t) (void *user_data);
struct l_settings *l_settings_new(void);
+struct l_settings *l_settings_clone(const struct l_settings *settings);
+
void l_settings_free(struct l_settings *settings);
DEFINE_CLEANUP_FUNC(l_settings_free);
--
2.31.1
4 months, 3 weeks
[PATCH 1/5] settings: add l_settings_clone
by James Prestwood
Returns identical copy of settings
---
ell/ell.sym | 1 +
ell/settings.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
ell/settings.h | 2 ++
3 files changed, 65 insertions(+)
diff --git a/ell/ell.sym b/ell/ell.sym
index 60c5525..827e68c 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -452,6 +452,7 @@ global:
l_ringbuf_append;
/* settings */
l_settings_new;
+ l_settings_clone;
l_settings_free;
l_settings_load_from_data;
l_settings_to_data;
diff --git a/ell/settings.c b/ell/settings.c
index 6958e12..a553ec0 100644
--- a/ell/settings.c
+++ b/ell/settings.c
@@ -116,6 +116,68 @@ LIB_EXPORT struct l_settings *l_settings_new(void)
return settings;
}
+static void copy_key_value_foreach(void *data, void *user_data)
+{
+ struct setting_data *s = data;
+ struct l_queue *settings = user_data;
+ struct setting_data *copy = l_new(struct setting_data, 1);
+
+ copy->key = l_strdup(s->key);
+ copy->value = l_strdup(s->value);
+
+ l_queue_push_head(settings, copy);
+}
+
+static void copy_group_foreach(void *data, void *user_data)
+{
+ struct group_data *group = data;
+ struct l_queue *groups = user_data;
+ struct group_data *copy = l_new(struct group_data, 1);
+
+ copy->name = l_strdup(group->name);
+ copy->settings = l_queue_new();
+
+ l_queue_push_head(groups, copy);
+
+ l_queue_foreach(group->settings, copy_key_value_foreach,
+ copy->settings);
+}
+
+static void copy_embedded_foreach(void *data, void *user_data)
+{
+ struct embedded_group_data *embedded = data;
+ struct l_queue *groups = user_data;
+ struct embedded_group_data *copy;
+
+ copy = l_malloc(sizeof(struct embedded_group_data) +
+ embedded->len + 1);
+ copy->name = l_strdup(embedded->name);
+
+ memcpy(copy->type, embedded->type, sizeof(embedded->type));
+ copy->len = embedded->len;
+ memcpy(copy->data, embedded->data, embedded->len);
+ copy->data[embedded->len] = '\0';
+
+ l_queue_push_tail(groups, copy);
+}
+
+LIB_EXPORT struct l_settings *l_settings_clone(
+ const struct l_settings *settings)
+{
+ struct l_settings *copy;
+
+ if (unlikely(!settings))
+ return NULL;
+
+ copy = l_settings_new();
+
+ l_queue_foreach(settings->groups, copy_group_foreach, copy->groups);
+ l_queue_foreach(settings->embedded_groups, copy_embedded_foreach,
+ copy->embedded_groups);
+
+ return copy;
+}
+
LIB_EXPORT void l_settings_free(struct l_settings *settings)
{
if (unlikely(!settings))
diff --git a/ell/settings.h b/ell/settings.h
index 9262ab9..f094ef5 100644
--- a/ell/settings.h
+++ b/ell/settings.h
@@ -37,6 +37,8 @@ typedef void (*l_settings_debug_cb_t) (const char *str, void *user_data);
typedef void (*l_settings_destroy_cb_t) (void *user_data);
struct l_settings *l_settings_new(void);
+struct l_settings *l_settings_clone(const struct l_settings *settings);
+
void l_settings_free(struct l_settings *settings);
DEFINE_CLEANUP_FUNC(l_settings_free);
--
2.31.1
4 months, 3 weeks