[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
2 months, 3 weeks
[PATCH] ecc: make l_ecc_point_from_data const time (for compressed points)
by James Prestwood
This only alters the two compressed point types as there isn't a security
reason to make the function const time for compliant/full point data as
these are never used in conjunction with compressed points.
The timing difference came down mainly to the conditional _vli_mod_sub call
which was only called depending on the first bit of p->y. More subtly the
check differered between BIT0 and BIT1 by a '!' operation which would result
in an additional instruction.
This patch addresses the '!' operation by checking if the subtraction is
needed and considering both compressed types in that logic.
For the subtraction, it is now done unconditionally and the result is stored
in a temporary variable. Then l_secure_select is used to copy the data to
p->y, or back into the temporary variable depending on if 'need_sub' evaluated
to true.
---
ell/ecc.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/ell/ecc.c b/ell/ecc.c
index 24b7cff..5830e01 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -535,6 +535,8 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
{
struct l_ecc_point *p;
size_t bytes = curve->ndigits * 8;
+ uint64_t tmp[L_ECC_MAX_DIGITS];
+ bool sub;
if (!data)
return NULL;
@@ -554,20 +556,18 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
break;
case L_ECC_POINT_TYPE_COMPRESSED_BIT0:
- if (!_ecc_compute_y(curve, p->y, p->x))
- goto failed;
-
- if (!(p->y[0] & 1))
- _vli_mod_sub(p->y, curve->p, p->y, curve->p,
- curve->ndigits);
- break;
case L_ECC_POINT_TYPE_COMPRESSED_BIT1:
if (!_ecc_compute_y(curve, p->y, p->x))
goto failed;
- if (p->y[0] & 1)
- _vli_mod_sub(p->y, curve->p, p->y, curve->p,
- curve->ndigits);
+ sub = ((type == L_ECC_POINT_TYPE_COMPRESSED_BIT0 &&
+ !(p->y[0] & 1)) ||
+ (type == L_ECC_POINT_TYPE_COMPRESSED_BIT1 &&
+ (p->y[0] & 1)));
+
+ _vli_mod_sub(tmp, curve->p, p->y, curve->p, curve->ndigits);
+
+ l_secure_select(sub, tmp, p->y, p->y, curve->ndigits * 8);
break;
case L_ECC_POINT_TYPE_FULL:
--
2.31.1
3 months, 2 weeks
[PATCH v2] dhcp: handle multiple offers from the same server
by James Prestwood
It was found that some DHCP servers send multiple offers on occation. Whether
this is a bug or not its been seen in products and ELL should handle this
gracefully.
The issue comes down to these DHCP servers expecting a request associated with
the last offer they send. The existing behavior in ELL is to ignore all offers
after the initial, and continue resending requests for the original offer. When
this happens the DHCP server never responds with an ACK.
The spec briefly outlines multiple DHCP offers but in the context of multiple
DHCP servers rather than multiple offers from the same DHCP server. In any
case its left up to the DHCP client to choose whatever offer it wants, so this
is what ELL will do.
Now only the last offer will be used while in the REQUESTING state. If another
offer comes in before the ACK, that offer will be used and a new request will
be sent out. Note this is only the case when the offers contain the same
server ID as the first offer sent (this eliminates the multi DHCP server case
and will maintain existing behavior, where the first offer is selected always).
---
ell/dhcp.c | 62 ++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 49 insertions(+), 13 deletions(-)
v2:
- Added a debug print in the multiple offer case
diff --git a/ell/dhcp.c b/ell/dhcp.c
index be03697..e2d18fc 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -757,6 +757,7 @@ static int dhcp_client_receive_offer(struct l_dhcp_client *client,
size_t len)
{
struct dhcp_message_iter iter;
+ struct l_dhcp_lease *lease;
CLIENT_DEBUG("");
@@ -766,15 +767,55 @@ static int dhcp_client_receive_offer(struct l_dhcp_client *client,
if (!_dhcp_message_iter_init(&iter, offer, len))
return -EINVAL;
- client->lease = _dhcp_lease_parse_options(&iter);
- if (!client->lease)
+ lease = _dhcp_lease_parse_options(&iter);
+ if (!lease)
return -ENOMSG;
+ /*
+ * Received another offer. In the case of multiple DHCP servers we want
+ * to ignore it and continue using the first offer. If this is from the
+ * same server its likely a buggy DHCP implementation and we should
+ * use the last offer it sends.
+ */
+ if (client->lease) {
+ if (client->lease->server_address != lease->server_address) {
+ _dhcp_lease_free(lease);
+ return -ENOMSG;
+ }
+
+ CLIENT_DEBUG("Server sent another offer, using it instead");
+
+ _dhcp_lease_free(client->lease);
+ }
+
+ client->lease = lease;
+
client->lease->address = offer->yiaddr;
return 0;
}
+static bool dhcp_client_handle_offer(struct l_dhcp_client *client,
+ const struct dhcp_message *message,
+ size_t len)
+{
+ if (dhcp_client_receive_offer(client, message, len) < 0)
+ return false;
+
+ CLIENT_ENTER_STATE(DHCP_STATE_REQUESTING);
+ client->attempt = 1;
+
+ if (dhcp_client_send_request(client) < 0) {
+ l_dhcp_client_stop(client);
+
+ return false;
+ }
+
+ l_timeout_modify_ms(client->timeout_resend, dhcp_fuzz_secs(4));
+
+ return true;
+}
+
static void dhcp_client_rx_message(const void *data, size_t len, void *userdata,
const uint8_t *saddr)
{
@@ -832,21 +873,16 @@ static void dhcp_client_rx_message(const void *data, size_t len, void *userdata,
if (msg_type != DHCP_MESSAGE_TYPE_OFFER)
return;
- if (dhcp_client_receive_offer(client, message, len) < 0)
+ if (!dhcp_client_handle_offer(client, message, len))
return;
- CLIENT_ENTER_STATE(DHCP_STATE_REQUESTING);
- client->attempt = 1;
-
- if (dhcp_client_send_request(client) < 0) {
- l_dhcp_client_stop(client);
-
- return;
- }
-
- l_timeout_modify_ms(client->timeout_resend, dhcp_fuzz_secs(4));
break;
case DHCP_STATE_REQUESTING:
+ if (msg_type == DHCP_MESSAGE_TYPE_OFFER) {
+ dhcp_client_handle_offer(client, message, len);
+ return;
+ }
+ /* Fall through */
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
receive_rapid_commit:
--
2.31.1
3 months, 2 weeks
[PATCH] dhcp: handle multiple offers from the same server
by James Prestwood
It was found that some DHCP servers send multiple offers on occation. Whether
this is a bug or not its been seen in products and ELL should handle this
gracefully.
The issue comes down to these DHCP servers expecting a request associated with
the last offer they send. The existing behavior in ELL is to ignore all offers
after the initial, and continue resending requests for the original offer. When
this happens the DHCP server never responds with an ACK.
The spec briefly outlines multiple DHCP offers but in the context of multiple
DHCP servers rather than multiple offers from the same DHCP server. In any
case its left up to the DHCP client to choose whatever offer it wants, so this
is what ELL will do.
Now only the last offer will be used while in the REQUESTING state. If another
offer comes in before the ACK, that offer will be used and a new request will
be sent out. Note this is only the case when the offers contain the same
server ID as the first offer sent (this eliminates the multi DHCP server case
and will maintain existing behavior, where the first offer is selected always).
---
ell/dhcp.c | 60 ++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 13 deletions(-)
diff --git a/ell/dhcp.c b/ell/dhcp.c
index be03697..66e4b8e 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -757,6 +757,7 @@ static int dhcp_client_receive_offer(struct l_dhcp_client *client,
size_t len)
{
struct dhcp_message_iter iter;
+ struct l_dhcp_lease *lease;
CLIENT_DEBUG("");
@@ -766,15 +767,53 @@ static int dhcp_client_receive_offer(struct l_dhcp_client *client,
if (!_dhcp_message_iter_init(&iter, offer, len))
return -EINVAL;
- client->lease = _dhcp_lease_parse_options(&iter);
- if (!client->lease)
+ lease = _dhcp_lease_parse_options(&iter);
+ if (!lease)
return -ENOMSG;
+ /*
+ * Received another offer. In the case of multiple DHCP servers we want
+ * to ignore it and continue using the first offer. If this is from the
+ * same server its likely a buggy DHCP implementation and we need to
+ * use the last offer it sends.
+ */
+ if (client->lease) {
+ if (client->lease->server_address != lease->server_address) {
+ _dhcp_lease_free(lease);
+ return -ENOMSG;
+ }
+
+ _dhcp_lease_free(client->lease);
+ }
+
+ client->lease = lease;
+
client->lease->address = offer->yiaddr;
return 0;
}
+static bool dhcp_client_handle_offer(struct l_dhcp_client *client,
+ const struct dhcp_message *message,
+ size_t len)
+{
+ if (dhcp_client_receive_offer(client, message, len) < 0)
+ return false;
+
+ CLIENT_ENTER_STATE(DHCP_STATE_REQUESTING);
+ client->attempt = 1;
+
+ if (dhcp_client_send_request(client) < 0) {
+ l_dhcp_client_stop(client);
+
+ return false;
+ }
+
+ l_timeout_modify_ms(client->timeout_resend, dhcp_fuzz_secs(4));
+
+ return true;
+}
+
static void dhcp_client_rx_message(const void *data, size_t len, void *userdata,
const uint8_t *saddr)
{
@@ -832,21 +871,16 @@ static void dhcp_client_rx_message(const void *data, size_t len, void *userdata,
if (msg_type != DHCP_MESSAGE_TYPE_OFFER)
return;
- if (dhcp_client_receive_offer(client, message, len) < 0)
+ if (!dhcp_client_handle_offer(client, message, len))
return;
- CLIENT_ENTER_STATE(DHCP_STATE_REQUESTING);
- client->attempt = 1;
-
- if (dhcp_client_send_request(client) < 0) {
- l_dhcp_client_stop(client);
-
- return;
- }
-
- l_timeout_modify_ms(client->timeout_resend, dhcp_fuzz_secs(4));
break;
case DHCP_STATE_REQUESTING:
+ if (msg_type == DHCP_MESSAGE_TYPE_OFFER) {
+ dhcp_client_handle_offer(client, message, len);
+ return;
+ }
+ /* Fall through */
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
receive_rapid_commit:
--
2.31.1
3 months, 3 weeks
[PATCH] acd: remove 'No target or source conflict' print
by James Prestwood
This is quite common and expected with ACD, and printing it serves
no useful purpose. The kind of debugging that is important is when
a conflict is detected.
---
ell/acd.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/ell/acd.c b/ell/acd.c
index 4216898..3c8e7fe 100644
--- a/ell/acd.c
+++ b/ell/acd.c
@@ -281,11 +281,8 @@ static bool acd_read_handler(struct l_io *io, void *user_data)
target_conflict = probe &&
!memcmp(arp.arp_tpa, &acd->ip, sizeof(uint32_t));
- if (!source_conflict && !target_conflict) {
- ACD_DEBUG("No target or source conflict detected for "NIPQUAD_FMT,
- NIPQUAD(acd->ip));
+ if (!source_conflict && !target_conflict)
return true;
- }
switch (acd->state) {
case ACD_STATE_PROBE:
--
2.31.1
3 months, 3 weeks
[PATCH v2 1/2] ecc: enforce strict length with l_ecc_point_from_data
by James Prestwood
This add some extra convenience to users of l_ecc_point_from_data
allowing the exact length to be verified in addition to creating
the point.
---
ell/ecc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ell/ecc.c b/ell/ecc.c
index a16b1c0..f1adcc4 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -538,8 +538,11 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
if (!data)
return NULL;
- /* In all cases there should be an X coordinate in data */
- if (len < bytes)
+ /* Verify the data length matches a full point or X coordinate */
+ if (type == L_ECC_POINT_TYPE_FULL) {
+ if (len != bytes * 2)
+ return NULL;
+ } else if (len != bytes)
return NULL;
p = l_ecc_point_new(curve);
@@ -570,9 +573,6 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
break;
case L_ECC_POINT_TYPE_FULL:
- if (len < bytes * 2)
- goto failed;
-
_ecc_be2native(p->y, (void *) data + bytes, curve->ndigits);
if (!ecc_valid_point(p))
--
2.31.1
4 months
[PATCH] ecc: enforce strict length with l_ecc_point_from_data
by James Prestwood
This add some extra convenience to users of l_ecc_point_from_data
allowing the exact length to be verified in addition to creating
the point.
---
ell/ecc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ell/ecc.c b/ell/ecc.c
index a16b1c0..f1adcc4 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -538,8 +538,11 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
if (!data)
return NULL;
- /* In all cases there should be an X coordinate in data */
- if (len < bytes)
+ /* Verify the data length matches a full point or X coordinate */
+ if (type == L_ECC_POINT_TYPE_FULL) {
+ if (len != bytes * 2)
+ return NULL;
+ } else if (len != bytes)
return NULL;
p = l_ecc_point_new(curve);
@@ -570,9 +573,6 @@ LIB_EXPORT struct l_ecc_point *l_ecc_point_from_data(
break;
case L_ECC_POINT_TYPE_FULL:
- if (len < bytes * 2)
- goto failed;
-
_ecc_be2native(p->y, (void *) data + bytes, curve->ndigits);
if (!ecc_valid_point(p))
--
2.31.1
4 months
[PATCH] ecc: add l_ecc_point_y_isodd
by James Prestwood
This is required to know how a compressed point will be interpreted
after sending the raw (compressed) X coordiate.
---
ell/ecc.c | 5 +++++
ell/ecc.h | 1 +
ell/ell.sym | 1 +
3 files changed, 7 insertions(+)
diff --git a/ell/ecc.c b/ell/ecc.c
index 5830e01..c934da0 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -735,6 +735,11 @@ LIB_EXPORT ssize_t l_ecc_point_get_y(const struct l_ecc_point *p, void *y,
return p->curve->ndigits * 8;
}
+LIB_EXPORT bool l_ecc_point_y_isodd(const struct l_ecc_point *p)
+{
+ return p->y[0] & 1;
+}
+
LIB_EXPORT ssize_t l_ecc_point_get_data(const struct l_ecc_point *p, void *buf,
size_t len)
{
diff --git a/ell/ecc.h b/ell/ecc.h
index 84a16c2..0bddd0e 100644
--- a/ell/ecc.h
+++ b/ell/ecc.h
@@ -69,6 +69,7 @@ struct l_ecc_point *l_ecc_point_clone(const struct l_ecc_point *p);
const struct l_ecc_curve *l_ecc_point_get_curve(const struct l_ecc_point *p);
ssize_t l_ecc_point_get_x(const struct l_ecc_point *p, void *x, size_t xlen);
ssize_t l_ecc_point_get_y(const struct l_ecc_point *p, void *y, size_t ylen);
+bool l_ecc_point_y_isodd(const struct l_ecc_point *p);
ssize_t l_ecc_point_get_data(const struct l_ecc_point *p, void *buf, size_t len);
void l_ecc_point_free(struct l_ecc_point *p);
diff --git a/ell/ell.sym b/ell/ell.sym
index 51db458..a65ee6d 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -572,6 +572,7 @@ global:
l_ecc_point_from_data;
l_ecc_point_get_x;
l_ecc_point_get_y;
+ l_ecc_point_y_isodd;
l_ecc_point_get_data;
l_ecc_point_inverse;
l_ecc_point_multiply;
--
2.31.1
4 months
[PATCH 1/5] icmp6: Allow multiple event handlers and clean up
by Andrew Zaborowski
Allow registering multiple event handlers and rename
l_icmp6_client_set_event_handler to l_icmp6_client_add_event_handler
accordingly. The use case is for a client like IWD to be able to track
routing information.
This also fixes a bug where the destroy callback passed to
l_icmp6_client_set_event_handler wasn't actually used except if
l_icmp6_client_set_event_handler was called again.
While there, add an event_data parameter to the event callback, rename
the "userdata" parameters to "user_data" for consistency and clean up an
extra empty line.
---
ell/dhcp6.c | 4 ++--
ell/ell.sym | 2 +-
ell/icmp6.c | 56 +++++++++++++++++++++++++++++++++++++++--------------
ell/icmp6.h | 8 ++++----
4 files changed, 48 insertions(+), 22 deletions(-)
diff --git a/ell/dhcp6.c b/ell/dhcp6.c
index 3e38ff2..40c6f3a 100644
--- a/ell/dhcp6.c
+++ b/ell/dhcp6.c
@@ -1467,7 +1467,7 @@ static void dhcp6_client_send_initial(struct l_dhcp6_client *client)
static void dhcp6_client_icmp6_event(struct l_icmp6_client *icmp6,
enum l_icmp6_client_event event,
- void *user_data)
+ void *event_data, void *user_data)
{
struct l_dhcp6_client *client = user_data;
@@ -1521,7 +1521,7 @@ LIB_EXPORT struct l_dhcp6_client *l_dhcp6_client_new(uint32_t ifindex)
client->request_na = true;
client->icmp6 = l_icmp6_client_new(ifindex);
- l_icmp6_client_set_event_handler(client->icmp6,
+ l_icmp6_client_add_event_handler(client->icmp6,
dhcp6_client_icmp6_event,
client, NULL);
diff --git a/ell/ell.sym b/ell/ell.sym
index 51db458..8da344e 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -679,7 +679,7 @@ global:
l_icmp6_client_start;
l_icmp6_client_stop;
l_icmp6_client_get_router;
- l_icmp6_client_set_event_handler;
+ l_icmp6_client_add_event_handler;
l_icmp6_client_set_debug;
l_icmp6_client_set_address;
l_icmp6_client_set_nodelay;
diff --git a/ell/icmp6.c b/ell/icmp6.c
index 42fe67d..6b1652c 100644
--- a/ell/icmp6.c
+++ b/ell/icmp6.c
@@ -237,6 +237,12 @@ static int icmp6_receive(int s, void *buf, size_t buf_len, struct in6_addr *src)
return 0;
}
+struct icmp6_event_handler_entry {
+ l_icmp6_client_event_cb_t handle;
+ void *user_data;
+ l_icmp6_destroy_cb_t destroy;
+};
+
struct l_icmp6_client {
uint32_t ifindex;
uint8_t mac[6];
@@ -249,9 +255,7 @@ struct l_icmp6_client {
uint32_t route_priority;
struct l_queue *routes;
- l_icmp6_client_event_cb_t event_handler;
- void *event_data;
- l_icmp6_destroy_cb_t event_destroy;
+ struct l_queue *event_handlers;
l_icmp6_debug_cb_t debug_handler;
l_icmp6_destroy_cb_t debug_destroy;
@@ -262,10 +266,17 @@ struct l_icmp6_client {
};
static inline void icmp6_client_event_notify(struct l_icmp6_client *client,
- enum l_icmp6_client_event event)
+ enum l_icmp6_client_event event,
+ void *event_data)
{
- if (client->event_handler)
- client->event_handler(client, event, client->event_data);
+ const struct l_queue_entry *entry;
+
+ for (entry = l_queue_get_entries(client->event_handlers); entry;
+ entry = entry->next) {
+ struct icmp6_event_handler_entry *handler = entry->data;
+
+ handler->handle(client, event, event_data, handler->user_data);
+ }
}
static bool icmp6_client_remove_route(void *data, void *user_data)
@@ -343,7 +354,8 @@ static int icmp6_client_handle_message(struct l_icmp6_client *client,
if (!client->ra) {
client->ra = r;
icmp6_client_event_notify(client,
- L_ICMP6_CLIENT_EVENT_ROUTER_FOUND);
+ L_ICMP6_CLIENT_EVENT_ROUTER_FOUND,
+ NULL);
/* DHCP6 client may have stopped us */
if (!client->ra)
@@ -446,6 +458,16 @@ LIB_EXPORT struct l_icmp6_client *l_icmp6_client_new(uint32_t ifindex)
return client;
}
+static void icmp6_event_handler_destroy(void *data)
+{
+ struct icmp6_event_handler_entry *handler = data;
+
+ if (handler->destroy)
+ handler->destroy(handler->user_data);
+
+ l_free(handler);
+}
+
LIB_EXPORT void l_icmp6_client_free(struct l_icmp6_client *client)
{
if (unlikely(!client))
@@ -453,6 +475,7 @@ LIB_EXPORT void l_icmp6_client_free(struct l_icmp6_client *client)
l_icmp6_client_stop(client);
l_queue_destroy(client->routes, NULL);
+ l_queue_destroy(client->event_handlers, icmp6_event_handler_destroy);
l_free(client);
}
@@ -537,20 +560,24 @@ LIB_EXPORT const struct l_icmp6_router *l_icmp6_client_get_router(
return client->ra;
}
-LIB_EXPORT bool l_icmp6_client_set_event_handler(struct l_icmp6_client *client,
+LIB_EXPORT bool l_icmp6_client_add_event_handler(struct l_icmp6_client *client,
l_icmp6_client_event_cb_t handler,
- void *userdata,
+ void *user_data,
l_icmp6_destroy_cb_t destroy)
{
+ struct icmp6_event_handler_entry *handler_entry;
+
if (unlikely(!client))
return false;
- if (client->event_destroy)
- client->event_destroy(client->event_data);
+ if (!client->event_handlers)
+ client->event_handlers = l_queue_new();
- client->event_handler = handler;
- client->event_data = userdata;
- client->event_destroy = destroy;
+ handler_entry = l_new(struct icmp6_event_handler_entry, 1);
+ handler_entry->handle = handler;
+ handler_entry->user_data = user_data;
+ handler_entry->destroy = destroy;
+ l_queue_push_head(client->event_handlers, handler_entry);
return true;
}
@@ -683,7 +710,6 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
opts_len -= l;
}
-
r = _icmp6_router_new();
memcpy(r->address, src, sizeof(r->address));
r->prefixes = l_new(struct route_info, n_prefixes);
diff --git a/ell/icmp6.h b/ell/icmp6.h
index b2231c9..9ce2e24 100644
--- a/ell/icmp6.h
+++ b/ell/icmp6.h
@@ -38,10 +38,10 @@ enum l_icmp6_client_event {
};
typedef void (*l_icmp6_debug_cb_t)(const char *str, void *user_data);
-typedef void (*l_icmp6_destroy_cb_t)(void *userdata);
+typedef void (*l_icmp6_destroy_cb_t)(void *user_data);
typedef void (*l_icmp6_client_event_cb_t)(struct l_icmp6_client *client,
enum l_icmp6_client_event event,
- void *userdata);
+ void *event_data, void *user_data);
struct l_icmp6_client *l_icmp6_client_new(uint32_t ifindex);
void l_icmp6_client_free(struct l_icmp6_client *client);
@@ -51,9 +51,9 @@ bool l_icmp6_client_stop(struct l_icmp6_client *client);
const struct l_icmp6_router *l_icmp6_client_get_router(
struct l_icmp6_client *client);
-bool l_icmp6_client_set_event_handler(struct l_icmp6_client *client,
+bool l_icmp6_client_add_event_handler(struct l_icmp6_client *client,
l_icmp6_client_event_cb_t handler,
- void *userdata,
+ void *user_data,
l_icmp6_destroy_cb_t destroy);
bool l_icmp6_client_set_debug(struct l_icmp6_client *client,
l_icmp6_debug_cb_t function,
--
2.32.0
4 months, 2 weeks
[PATCH 1/4] rtnl: Add l_rtnl_route_set_gateway
by Andrew Zaborowski
Allow creating prefix routes for off-link prefixes, i.e. ones that
should be routed through a gateway.
---
ell/ell.sym | 1 +
ell/rtnl.c | 16 ++++++++++++++++
ell/rtnl.h | 1 +
3 files changed, 18 insertions(+)
diff --git a/ell/ell.sym b/ell/ell.sym
index 51db458..e581add 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -633,6 +633,7 @@ global:
l_rtnl_route_free;
l_rtnl_route_get_family;
l_rtnl_route_get_gateway;
+ l_rtnl_route_set_gateway;
l_rtnl_route_get_lifetime;
l_rtnl_route_set_lifetime;
l_rtnl_route_get_mtu;
diff --git a/ell/rtnl.c b/ell/rtnl.c
index 4a1a248..ee6dc9a 100644
--- a/ell/rtnl.c
+++ b/ell/rtnl.c
@@ -403,6 +403,22 @@ LIB_EXPORT bool l_rtnl_route_get_gateway(const struct l_rtnl_route *rt,
out_buf);
}
+LIB_EXPORT bool l_rtnl_route_set_gateway(struct l_rtnl_route *rt,
+ const char *address)
+{
+ if (unlikely(!rt))
+ return false;
+
+ switch (rt->family) {
+ case AF_INET:
+ return inet_pton(AF_INET, address, &rt->gw.in_addr) == 1;
+ case AF_INET6:
+ return inet_pton(AF_INET6, address, &rt->gw.in6_addr) == 1;
+ default:
+ return false;
+ }
+}
+
LIB_EXPORT uint32_t l_rtnl_route_get_lifetime(const struct l_rtnl_route *rt)
{
if (unlikely(!rt))
diff --git a/ell/rtnl.h b/ell/rtnl.h
index 274816c..70cbaec 100644
--- a/ell/rtnl.h
+++ b/ell/rtnl.h
@@ -69,6 +69,7 @@ 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);
+bool l_rtnl_route_set_gateway(struct l_rtnl_route *rt, const char *address);
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_mtu(const struct l_rtnl_route *rt);
--
2.32.0
4 months, 2 weeks