[PATCHv2] gpio: add simple get/set helpers for GPIO lines
by Martin Hundebøll
The Linux kernel GPIO api operates with chips, lines, handles, and
events.
The chip and line structures represent info about gpio chips, and
gpio lines, respectively. They are used to e.g. lookup a line with a
certain name, and/or line flags.
The handle structure is used to "obtain" a handle to one or more gpio
lines on a chip. Until the file descriptor in this handle is closed, the
gpio lines cannot be used by others. The same file descriptor is used
when setting or getting the line values (one can also set the initial
value when obtaining handles for output lines).
The event structure is used to get a file descriptor that can be used
with select/poll to wait for changes in line levels.
This commit add simple support for setting and getting the value for a
single gpio line. It does so by obtaining a line handle to get/set the
value, and then release the handle immediately again.
Functionality that could be implemented, but is postponed until the need
arises includes:
* looking up a gpio line by its name
* setting/getting multiple gpio lines with a single function
* waiting for events
* holding on to handles
Some of the above probably require adding structures to represent gpio
lines and events, while handles should be private to the class.
---
Changes since v1:
* added gpiochip info and corresponding getters
* changed "line" to "line_num" a few places
Changes since RFC:
* added gpio.h to ell.h
* changed copyright to Geanix
* open gpiochip in l_gpio_chip_new()
* open gpiochip read-only
* added input checks
* clear ioctl structs with memset instead of = {0}
* reorder error-paths
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/ell.sym | 7 +++
ell/gpio.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/gpio.h | 49 +++++++++++++++
5 files changed, 236 insertions(+), 2 deletions(-)
create mode 100644 ell/gpio.c
create mode 100644 ell/gpio.h
diff --git a/Makefile.am b/Makefile.am
index 8401972..0ecb9a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/gpio.h
lib_LTLIBRARIES = ell/libell.la
@@ -119,7 +120,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/gpio.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.h b/ell/ell.h
index aab6417..fb1dd79 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -59,3 +59,4 @@
#include <ell/cert.h>
#include <ell/ecc.h>
#include <ell/ecdh.h>
+#include <ell/gpio.h>
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..793e4c3 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -463,6 +463,13 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+ /* gpio */
+ l_gpio_chip_new;
+ l_gpio_chip_free;
+ l_gpio_chip_get_label;
+ l_gpio_chip_get_num_lines;
+ l_gpio_chip_get_line_value;
+ l_gpio_chip_set_line_value;
local:
*;
};
diff --git a/ell/gpio.c b/ell/gpio.c
new file mode 100644
index 0000000..83032f9
--- /dev/null
+++ b/ell/gpio.c
@@ -0,0 +1,175 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Geanix. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/gpio.h>
+
+#include "util.h"
+#include "gpio.h"
+#include "private.h"
+
+struct l_gpio_chip {
+ int fd;
+ char *label;
+ uint32_t num_lines;
+};
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_chip_new(const char *chip_name)
+{
+ struct l_gpio_chip *chip;
+ struct gpiochip_info info;
+ char *path;
+ int ret;
+
+ if (!chip_name)
+ return NULL;
+
+ chip = l_new(struct l_gpio_chip, 1);
+
+ path = l_strdup_printf("/dev/%s", chip_name);
+ chip->fd = open(path, O_RDONLY | O_CLOEXEC);
+ l_free(path);
+
+ if (chip->fd < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ memset(&info, 0, sizeof(info));
+
+ ret = ioctl(chip->fd, GPIO_GET_CHIPINFO_IOCTL, &info);
+ if (ret < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ if (info.label)
+ chip->label = l_strndup(info.label, sizeof(info.label));
+
+ chip->num_lines = info.lines;
+
+ return chip;
+}
+
+LIB_EXPORT void l_gpio_chip_free(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return;
+
+ if (chip->fd >= 0)
+ close(chip->fd);
+
+ l_free(chip->label);
+ l_free(chip);
+}
+
+LIB_EXPORT const char *l_gpio_chip_get_label(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return NULL;
+
+ return chip->label;
+}
+
+LIB_EXPORT uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return 0;
+
+ return chip->num_lines;
+}
+
+LIB_EXPORT bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip,
+ uint32_t line_num, bool *value)
+{
+ struct gpiohandle_request req;
+ struct gpiohandle_data data;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (line_num >= chip->num_lines)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line_num;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_INPUT;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ memset(&data, 0, sizeof(data));
+
+ ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+
+ close(req.fd);
+
+ if (ret < 0)
+ return false;
+
+ if (value)
+ *value = !!data.values[0];
+
+ return true;
+}
+
+LIB_EXPORT bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip,
+ uint32_t line_num, bool value)
+{
+ struct gpiohandle_request req;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (line_num >= chip->num_lines)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line_num;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_OUTPUT;
+ req.default_values[0] = value;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ close(req.fd);
+
+ return true;
+}
diff --git a/ell/gpio.h b/ell/gpio.h
new file mode 100644
index 0000000..9f4ae6a
--- /dev/null
+++ b/ell/gpio.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_GPIO_H
+#define __ELL_GPIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_gpio_chip;
+
+struct l_gpio_chip *l_gpio_chip_new(const char *chip_name);
+void l_gpio_chip_free(struct l_gpio_chip *chip);
+
+const char *l_gpio_chip_get_label(struct l_gpio_chip *chip);
+uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip);
+bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip, uint32_t line_num,
+ bool *value);
+bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip, uint32_t line_num,
+ bool value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_GPIO_H */
--
2.20.0
3 years
[PATCH] key: Use KEYCTL_INVALIDATE in l_key_free
by Andrew Zaborowski
Replace the use of KEYCTL_REVOKE with KEYCTL_INVALIDE in
l_key(ring)_free. 10ff938dc758e36135c1e07370c2d06cf89d8620 improved the
behaiour of l_key_free with regards to the key quota freeing for cases
when the key was only linked to the internal session keyring. By using
KEYCTL_INVALIDATE we can achieve the same effect even if the key is
still linked to multiple keyrings and with just one operation instead of
two. keyctl(2):
KEYCTL_REVOKE (since Linux 2.6.10)
[...]
Revoke the key with the ID provided in arg2 (cast to key_serial_t).
The key is scheduled for garbage collection;
(In practice this means the key gets freed after 5 minutes)
KEYCTL_INVALIDATE (since Linux 3.5)
[...]
This operation marks the key as invalid and schedules immediate garbage
collection. The garbage collector removes the invalidated key from
all keyrings and deletes the key when its reference count reaches zero.
---
ell/key.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/ell/key.c b/ell/key.c
index 6c36655..304344f 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -138,11 +138,11 @@ static long kernel_update_key(int32_t serial, const void *payload, size_t len)
return result >= 0 ? result : -errno;
}
-static long kernel_revoke_key(int32_t serial)
+static long kernel_invalidate_key(int32_t serial)
{
long result;
- result = syscall(__NR_keyctl, KEYCTL_REVOKE, serial);
+ result = syscall(__NR_keyctl, KEYCTL_INVALIDATE, serial);
return result >= 0 ? result : -errno;
}
@@ -324,20 +324,11 @@ LIB_EXPORT void l_key_free(struct l_key *key)
return;
/*
- * Unlinking the key from internal_keyring, while not necessary,
- * causes the kernel's key garbage collector to run much sooner
- * than if the key is only revoked, at least under some kernel
- * versions and when the key is not linked to any other ring.
- * In practice this helps the user processes stay under the
- * per-user key quota (kernel.keys.maxkeys) which is difficult
- * to control when there's no way to reclaim the spot occupied
- * by the freed key until the GC runs and not even a way to
- * wait for the GC. That means that running many key
- * operations too fast may cause add_key to start failing
- * independent of how high the quota has been set.
+ * Use invalidate as, unlike revoke, this doesn't delay the
+ * key garbage collection and causes the quota used by the
+ * key to be released sooner and more predictably.
*/
- kernel_unlink_key(key->serial, internal_keyring);
- kernel_revoke_key(key->serial);
+ kernel_invalidate_key(key->serial);
l_free(key);
}
@@ -724,8 +715,7 @@ LIB_EXPORT void l_keyring_free(struct l_keyring *keyring)
if (unlikely(!keyring))
return;
- kernel_unlink_key(keyring->serial, internal_keyring);
- kernel_revoke_key(keyring->serial);
+ kernel_invalidate_key(keyring->serial);
l_free(keyring);
}
--
2.19.1
3 years, 5 months
[PATCH v2 1/2] time: basic utility for getting the system time
by James Prestwood
Timeouts are sometimes overkill for long timeouts, or timeouts that
don't require being immediately serviced once expired. For this
reason the 'time' module was added which allows you to get the system
clock time, as well as some basic APIs to check if two time values are
before/after one another, calculating an offset from a start time, and
finding the diff between two time values. This allows an application
to handle its own timeouts lazily with no tie to the main loop.
The APIs were modeled after the kernel APIs in jiffies.h
---
Makefile.am | 6 +++--
ell/ell.h | 1 +
ell/ell.sym | 7 ++++++
ell/time.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/time.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 151 insertions(+), 2 deletions(-)
create mode 100644 ell/time.c
create mode 100644 ell/time.h
diff --git a/Makefile.am b/Makefile.am
index 3eecbe0..1c089ec 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/time.h
lib_LTLIBRARIES = ell/libell.la
@@ -121,7 +122,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/time.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.h b/ell/ell.h
index aab6417..691bdb2 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -59,3 +59,4 @@
#include <ell/cert.h>
#include <ell/ecc.h>
#include <ell/ecdh.h>
+#include <ell/time.h>
diff --git a/ell/ell.sym b/ell/ell.sym
index 7643a25..d1fb2ff 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -485,6 +485,13 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+
+ /* time */
+ l_time_now;
+ l_time_after;
+ l_time_before;
+ l_time_offset;
+ l_time_diff;
local:
*;
};
diff --git a/ell/time.c b/ell/time.c
new file mode 100644
index 0000000..d49478c
--- /dev/null
+++ b/ell/time.c
@@ -0,0 +1,72 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+
+#include "time.h"
+#include "private.h"
+
+/**
+ * l_time_now:
+ *
+ * Get the running clocktime in microseconds
+ *
+ * Returns: Current clock time in microseconds
+ **/
+LIB_EXPORT uint64_t l_time_now(void)
+{
+ struct timespec now;
+
+ clock_gettime(CLOCK_BOOTTIME, &now);
+
+ return now.tv_sec * 1000000 + now.tv_nsec / 1000;
+}
+
+/**
+ * l_time_after
+ *
+ * Returns: True if time a is after time b
+ **/
+
+/**
+ * l_time_before
+ *
+ * Returns: True if time a is before time b
+ **/
+
+/**
+ * l_time_offset
+ *
+ * @time: Start time to calculate offset
+ * @offset: Amount of time to add to 'time'
+ *
+ * Adds an offset to a time value. This checks for overflow, and if detected
+ * returns ULONG_MAX.
+ *
+ * Returns: A time value 'time' + 'offset'. Or ULONG_MAX if time + offset
+ * exceeds ULONG_MAX.
+ **/
+
diff --git a/ell/time.h b/ell/time.h
new file mode 100644
index 0000000..227da91
--- /dev/null
+++ b/ell/time.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_TIME_H
+#define __ELL_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <limits.h>
+
+uint64_t l_time_now(void);
+
+static inline bool l_time_after(uint64_t a, uint64_t b)
+{
+ if ((int64_t)(b - a) < 0)
+ return true;
+
+ return false;
+}
+
+static inline bool l_time_before(uint64_t a, uint64_t b)
+{
+ return l_time_after(b, a);
+}
+
+static inline uint64_t l_time_offset(uint64_t time, uint64_t offset)
+{
+ /* check overflow */
+ if ((int64_t)(time + offset) <= 0)
+ return ULONG_MAX;
+
+ return time + offset;
+}
+
+static inline uint64_t l_time_diff(uint64_t a, uint64_t b)
+{
+ return (a < b) ? b - a : a - b;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_TIME_H */
--
2.17.1
3 years, 5 months
[PATCH] key: Work around keyctl_dh_params breakage in certain stable kernels
by Mat Martineau
These stable kernels had a change which renamed one of the members of
struct keyctl_dh_params and broke the ELL build:
v4.14.70, v4.14.71, v4.14.72
v4.18.8, v4.18.9, v4.18.10
Later stable releases in the v4.14.x and v4.18.x series reverted to the
previous member name.
This change allows ELL to build using the kernel declaration of the
struct for v4.20 and later, and provides a correct structure declaration
for older kernels.
---
ell/key.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/ell/key.c b/ell/key.c
index bd5b4ea..6c36655 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -39,12 +39,6 @@
#ifndef KEYCTL_DH_COMPUTE
#define KEYCTL_DH_COMPUTE 23
-
-struct keyctl_dh_params {
- int32_t private;
- int32_t prime;
- int32_t base;
-};
#endif
#ifndef KEYCTL_PKEY_QUERY
@@ -79,6 +73,20 @@ struct keyctl_pkey_params {
};
uint32_t __spare[7];
};
+
+/* Work around the missing (pre-4.7) or broken (4.14.{70,71,72} and
+ * 4.18.{8,9,10}) kernel declaration of struct keyctl_dh_params
+ */
+struct dh_params {
+ int32_t private;
+ int32_t prime;
+ int32_t base;
+};
+#else
+/* When KEYCTL_PKEY_QUERY is defined by the kernel, the
+ * struct keyctl_dh_params declaration is valid.
+ */
+#define dh_params keyctl_dh_params
#endif
#ifndef KEYCTL_RESTRICT_KEYRING
@@ -201,9 +209,9 @@ static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
{
long result;
- struct keyctl_dh_params params = { .private = private,
- .prime = prime,
- .base = base };
+ struct dh_params params = { .private = private,
+ .prime = prime,
+ .base = base };
result = syscall(__NR_keyctl, KEYCTL_DH_COMPUTE, ¶ms, payload, len,
NULL);
--
2.20.1
3 years, 5 months
[PATCH v2 1/2] key: Avoid using C++ keywords as param names.
by Ossama Othman
Rename the parameter names "public" and "private" to avoid conflicts
with the similarly named C++ keywords. Addresses compile-time errors
in C++ code that includes <ell/key.h>.
---
ell/key.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ell/key.h b/ell/key.h
index 024afc6..f1f95e1 100644
--- a/ell/key.h
+++ b/ell/key.h
@@ -70,16 +70,16 @@ ssize_t l_key_get_payload_size(struct l_key *key);
bool l_key_get_info(struct l_key *key, enum l_key_cipher_type cipher,
enum l_checksum_type checksum, size_t *bits,
- bool *public);
+ bool *out_public);
struct l_key *l_key_generate_dh_private(const void *prime_buf,
size_t prime_len);
-bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private,
+bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private_key,
struct l_key *prime,
void *payload, size_t *len);
-bool l_key_compute_dh_secret(struct l_key *other_public, struct l_key *private,
+bool l_key_compute_dh_secret(struct l_key *other_public, struct l_key *private_key,
struct l_key *prime,
void *payload, size_t *len);
--
2.17.1
3 years, 5 months
[PATCH 0/2] Correct ELL header errors included C++ code.
by Ossama Othman
Including <ell/ell.h> in C++ code revealed a few C++ related conflicts
in <ell/key.h>. These patches address those errors, and add a simple
C++ build test that enabled if a C++ compiler is found when maintainer
mode is enabled.
Ossama Othman (2):
key: Avoid using C++ keywords as param names.
unit: Added a minimal C++ build test.
.gitignore | 1 +
Makefile.am | 6 ++++++
configure.ac | 3 +++
ell/key.h | 6 +++---
unit/test-cxx-build.cpp | 42 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 55 insertions(+), 3 deletions(-)
create mode 100644 unit/test-cxx-build.cpp
--
2.17.1
3 years, 5 months
[PATCH] queue: Correct l_queue_foreach_remove() doc.
by Ossama Othman
Removed non-existent "destroy" parameter from l_queue_foreach_remove()
documentation.
---
ell/queue.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/ell/queue.c b/ell/queue.c
index 67f7093..0f6ed3e 100644
--- a/ell/queue.c
+++ b/ell/queue.c
@@ -495,7 +495,6 @@ LIB_EXPORT unsigned int l_queue_foreach_remove(struct l_queue *queue,
* @queue: queue object
* @function: callback function
* @user_data: user data given to callback function
- * @destroy: Destructor function to call on removal
*
* Remove the first entry in the @queue where the function returns #true.
*
--
2.17.1
3 years, 5 months
[PATCH] time: basic utility for getting the system time
by James Prestwood
Timeouts are sometimes overkill for long timeouts, or timeouts that
don't require being immediately serviced once expired. For this
reason the 'time' module was added which allows you to get the system
clock time, as well as some basic APIs to check if two time values are
before/after one another, and for calculating an offset from a start
time. This allows an application to handle its own timeouts lazily
with no tie to the main loop.
The APIs were modeled after the kernel APIs in jiffies.h
---
Makefile.am | 6 ++--
ell/ell.sym | 6 ++++
ell/time.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/time.h | 45 ++++++++++++++++++++++++++
4 files changed, 148 insertions(+), 2 deletions(-)
create mode 100644 ell/time.c
create mode 100644 ell/time.h
diff --git a/Makefile.am b/Makefile.am
index 3eecbe0..1c089ec 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/time.h
lib_LTLIBRARIES = ell/libell.la
@@ -121,7 +122,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/time.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.sym b/ell/ell.sym
index 7643a25..e67716e 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -485,6 +485,12 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+
+ /* time */
+ l_time_now;
+ l_time_after;
+ l_time_before;
+ l_time_offset;
local:
*;
};
diff --git a/ell/time.c b/ell/time.c
new file mode 100644
index 0000000..3c2b929
--- /dev/null
+++ b/ell/time.c
@@ -0,0 +1,93 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+#include <limits.h>
+
+#include "time.h"
+#include "private.h"
+
+/**
+ * l_time_now:
+ *
+ * Get the running clocktime in microseconds
+ *
+ * Returns: Current clock time in microseconds
+ **/
+LIB_EXPORT uint64_t l_time_now(void)
+{
+ struct timespec now;
+
+ clock_gettime(CLOCK_BOOTTIME, &now);
+
+ return now.tv_sec * 1000000 + now.tv_nsec / 1000;
+}
+
+/**
+ * l_time_after
+ *
+ * Returns: True if time a is after time b
+ **/
+LIB_EXPORT bool l_time_after(uint64_t a, uint64_t b)
+{
+ if ((int64_t)(b - a) < 0)
+ return true;
+
+ return false;
+}
+
+/**
+ * l_time_before
+ *
+ * Returns: True if time a is before time b
+ **/
+LIB_EXPORT bool l_time_before(uint64_t a, uint64_t b)
+{
+ return l_time_after(b, a);
+}
+
+/**
+ * l_time_offset
+ *
+ * @time: Start time to calculate offset
+ * @offset: Amount of time to add to 'time'
+ *
+ * Adds an offset to a time value. This checks for overflow, and if detected
+ * returns ULONG_MAX.
+ *
+ * Returns: A time value 'time' + 'offset'. Or ULONG_MAX if time + offset
+ * exceeds ULONG_MAX.
+ **/
+LIB_EXPORT uint64_t l_time_offset(uint64_t time, uint64_t offset)
+{
+ uint64_t added = time + offset;
+
+ /* check overflow */
+ if (!l_time_after(added, time))
+ return ULONG_MAX;
+
+ return added;
+}
diff --git a/ell/time.h b/ell/time.h
new file mode 100644
index 0000000..00c09cd
--- /dev/null
+++ b/ell/time.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_TIME_H
+#define __ELL_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+uint64_t l_time_now(void);
+
+bool l_time_after(uint64_t a, uint64_t b);
+
+bool l_time_before(uint64_t a, uint64_t b);
+
+uint64_t l_time_offset(uint64_t time, uint64_t offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_TIME_H */
--
2.17.1
3 years, 5 months
[PATCH 1/2] ecc: Add l_ecc_curve_get_scalar_bytes
by Andrew Zaborowski
Add a function to return the number of bytes used by the *_from_data
and *_get_data methods.
---
ell/ecc.c | 9 ++++++++-
ell/ecc.h | 1 +
ell/ell.sym | 6 ++++++
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/ell/ecc.c b/ell/ecc.c
index dd2e11a..eeb12dd 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -123,6 +123,14 @@ LIB_EXPORT const char *l_ecc_curve_get_name(const struct l_ecc_curve *curve)
return curve->name;
}
+LIB_EXPORT size_t l_ecc_curve_get_scalar_bytes(const struct l_ecc_curve *curve)
+{
+ if (unlikely(!curve))
+ return 0;
+
+ return curve->ndigits * 8;
+}
+
LIB_EXPORT const struct l_ecc_curve *l_ecc_curve_get_ike_group(
unsigned int group)
{
@@ -589,7 +597,6 @@ LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_random(
}
LIB_EXPORT ssize_t l_ecc_scalar_get_data(const struct l_ecc_scalar *c,
-
void *buf, size_t len)
{
if (len < c->curve->ndigits * 8)
diff --git a/ell/ecc.h b/ell/ecc.h
index e867ef9..26a5889 100644
--- a/ell/ecc.h
+++ b/ell/ecc.h
@@ -44,6 +44,7 @@ enum l_ecc_point_type {
const struct l_ecc_curve *l_ecc_curve_get(const char *name);
const char *l_ecc_curve_get_name(const struct l_ecc_curve *curve);
+size_t l_ecc_curve_get_scalar_bytes(const struct l_ecc_curve *curve);
const unsigned int *l_ecc_curve_get_supported_ike_groups(void);
const unsigned int *l_ecc_curve_get_supported_tls_groups(void);
const struct l_ecc_curve *l_ecc_curve_get_ike_group(unsigned int group);
diff --git a/ell/ell.sym b/ell/ell.sym
index 7643a25..828278b 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -460,7 +460,13 @@ global:
l_certchain_verify;
/* ecc */
l_ecc_curve_get;
+ l_ecc_curve_get_name;
+ l_ecc_curve_get_scalar_bytes;
l_ecc_curve_get_supported_groups;
+ l_ecc_curve_get_supported_ike_groups;
+ l_ecc_curve_get_supported_tls_groups;
+ l_ecc_curve_get_ike_group;
+ l_ecc_curve_get_tls_group;
l_ecc_curve_get_order;
l_ecc_curve_get_prime;
l_ecc_point_add;
--
2.19.1
3 years, 5 months
[PATCH 1/9] checksum: Refactor to remove loops and string operations
by Andrew Zaborowski
Various checksum methods, like is_supported, get_digest_length, would
look up the checksum data by building the algorithm name string and then
iterating over all checksum_info structs to find the matching name.
Change the checksum_info tables so that they're indexed by
l_checksum_type and the lookups are cheap and simple. Also drop the
copies of the algorithm name from struct l_checksum.
---
I've also tried changing l_checksum_get_digest_length to take a pointer
to a checksum object instad of checksum type so it could be used equally
for the primary algorithms and the HMAC and CMAC algorithms but iwd has
one use case where it's convenient to have the digest size before
creating the checksum object.
---
ell/checksum.c | 190 +++++++++++++++++++------------------------------
1 file changed, 73 insertions(+), 117 deletions(-)
diff --git a/ell/checksum.c b/ell/checksum.c
index 0bb16fd..fec7a69 100644
--- a/ell/checksum.c
+++ b/ell/checksum.c
@@ -68,25 +68,42 @@ struct sockaddr_alg {
#define SOL_ALG 279
#endif
-static struct {
+struct checksum_info {
+ enum l_checksum_type type;
const char *name;
uint8_t digest_len;
bool supported;
+};
+
+static struct checksum_info checksum_algs[] = {
+ [L_CHECKSUM_MD4] = { .name = "md4", .digest_len = 16 },
+ [L_CHECKSUM_MD5] = { .name = "md5", .digest_len = 16 },
+ [L_CHECKSUM_SHA1] = { .name = "sha1", .digest_len = 20 },
+ [L_CHECKSUM_SHA256] = { .name = "sha256", .digest_len = 32 },
+ [L_CHECKSUM_SHA384] = { .name = "sha384", .digest_len = 48 },
+ [L_CHECKSUM_SHA512] = { .name = "sha512", .digest_len = 64 },
+};
+
+static struct checksum_info checksum_cmac_aes_alg =
+ { .name = "cmac(aes)", .digest_len = 16 };
+
+static struct checksum_info checksum_hmac_algs[] = {
+ [L_CHECKSUM_MD4] = { .name = "hmac(md4)", .digest_len = 16 },
+ [L_CHECKSUM_MD5] = { .name = "hmac(md5)", .digest_len = 16 },
+ [L_CHECKSUM_SHA1] = { .name = "hmac(sha1)", .digest_len = 20 },
+ [L_CHECKSUM_SHA256] = { .name = "hmac(sha256)", .digest_len = 32 },
+ [L_CHECKSUM_SHA384] = { .name = "hmac(sha384)", .digest_len = 48 },
+ [L_CHECKSUM_SHA512] = { .name = "hmac(sha512)", .digest_len = 64 },
+};
+
+static const struct {
+ struct checksum_info *list;
+ size_t n;
} checksum_info_table[] = {
- { .name = "md4", .digest_len = 16 },
- { .name = "md5", .digest_len = 16 },
- { .name = "sha1", .digest_len = 20 },
- { .name = "sha256", .digest_len = 32 },
- { .name = "sha384", .digest_len = 48 },
- { .name = "sha512", .digest_len = 64 },
- { .name = "cmac(aes)", .digest_len = 16 },
- { .name = "hmac(md4)", .digest_len = 16 },
- { .name = "hmac(md5)", .digest_len = 16 },
- { .name = "hmac(sha1)", .digest_len = 20 },
- { .name = "hmac(sha256)", .digest_len = 32 },
- { .name = "hmac(sha384)", .digest_len = 48 },
- { .name = "hmac(sha512)", .digest_len = 64 },
- { .name = NULL, .digest_len = 0 },
+ { checksum_algs, L_ARRAY_SIZE(checksum_algs) },
+ { &checksum_cmac_aes_alg, 1 },
+ { checksum_hmac_algs, L_ARRAY_SIZE(checksum_hmac_algs) },
+ {}
};
/**
@@ -96,17 +113,16 @@ static struct {
* Checksum handling
*/
-#define is_valid_type(type) ((type) > L_CHECKSUM_NONE && \
- (type) <= L_CHECKSUM_SHA512)
+#define is_valid_index(array, i) ((i) >= 0 && (i) < L_ARRAY_SIZE(array))
/**
* l_checksum:
*
- * Opague object representing the checksum.
+ * Opaque object representing the checksum.
*/
struct l_checksum {
int sk;
- char alg_name[sizeof(((struct sockaddr_alg *) 0)->salg_name)];
+ const struct checksum_info *alg_info;
};
static int create_alg(const char *alg)
@@ -131,30 +147,6 @@ static int create_alg(const char *alg)
return sk;
}
-static const char *checksum_type_to_name(enum l_checksum_type type)
-{
- switch (type) {
- case L_CHECKSUM_NONE:
- return NULL;
- case L_CHECKSUM_MD4:
- return "md4";
- case L_CHECKSUM_MD5:
- return "md5";
- case L_CHECKSUM_SHA1:
- return "sha1";
- case L_CHECKSUM_SHA224:
- return "sha224";
- case L_CHECKSUM_SHA256:
- return "sha256";
- case L_CHECKSUM_SHA384:
- return "sha384";
- case L_CHECKSUM_SHA512:
- return "sha512";
- }
-
- return NULL;
-}
-
/**
* l_checksum_new:
* @type: checksum type
@@ -166,17 +158,15 @@ static const char *checksum_type_to_name(enum l_checksum_type type)
LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type)
{
struct l_checksum *checksum;
- const char *name;
int fd;
- if (!is_valid_type(type))
+ if (!is_valid_index(checksum_algs, type) || !checksum_algs[type].name)
return NULL;
checksum = l_new(struct l_checksum, 1);
+ checksum->alg_info = &checksum_algs[type];
- name = checksum_type_to_name(type);
-
- fd = create_alg(name);
+ fd = create_alg(checksum->alg_info->name);
if (fd < 0)
goto error;
@@ -186,8 +176,6 @@ LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type)
if (checksum->sk < 0)
goto error;
- strcpy(checksum->alg_name, name);
-
return checksum;
error:
@@ -219,7 +207,7 @@ LIB_EXPORT struct l_checksum *l_checksum_new_cmac_aes(const void *key,
return NULL;
}
- strcpy(checksum->alg_name, "cmac(aes)");
+ checksum->alg_info = &checksum_cmac_aes_alg;
return checksum;
}
@@ -228,18 +216,12 @@ LIB_EXPORT struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
{
struct l_checksum *checksum;
int fd;
- char name[sizeof(((struct sockaddr_alg *)0)->salg_name)];
- unsigned int r;
-
- if (!is_valid_type(type))
- return NULL;
- r = snprintf(name, sizeof(name), "hmac(%s)",
- checksum_type_to_name(type));
- if (r >= sizeof(name))
+ if (!is_valid_index(checksum_hmac_algs, type) ||
+ !checksum_hmac_algs[type].name)
return NULL;
- fd = create_alg(name);
+ fd = create_alg(checksum_hmac_algs[type].name);
if (fd < 0)
return NULL;
@@ -257,7 +239,7 @@ LIB_EXPORT struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
return NULL;
}
- strcpy(checksum->alg_name, name);
+ checksum->alg_info = &checksum_hmac_algs[type];
return checksum;
}
@@ -284,7 +266,7 @@ LIB_EXPORT struct l_checksum *l_checksum_clone(struct l_checksum *checksum)
return NULL;
}
- strcpy(clone->alg_name, checksum->alg_name);
+ clone->alg_info = checksum->alg_info;
return clone;
}
@@ -418,22 +400,13 @@ LIB_EXPORT ssize_t l_checksum_get_digest(struct l_checksum *checksum,
LIB_EXPORT char *l_checksum_get_string(struct l_checksum *checksum)
{
unsigned char digest[64];
- unsigned int i;
if (unlikely(!checksum))
return NULL;
l_checksum_get_digest(checksum, digest, sizeof(digest));
- for (i = 0; checksum_info_table[i].name; i++) {
- if (strcmp(checksum_info_table[i].name, checksum->alg_name))
- continue;
-
- return l_util_hexstring(digest,
- checksum_info_table[i].digest_len);
- }
-
- return NULL;
+ return l_util_hexstring(digest, checksum->alg_info->digest_len);
}
static void init_supported()
@@ -441,7 +414,7 @@ static void init_supported()
static bool initialized = false;
struct sockaddr_alg salg;
int sk;
- int i;
+ unsigned int i, j;
if (likely(initialized))
return;
@@ -456,74 +429,57 @@ static void init_supported()
salg.salg_family = AF_ALG;
strcpy((char *) salg.salg_type, "hash");
- for (i = 0; checksum_info_table[i].name; i++) {
- strcpy((char *) salg.salg_name, checksum_info_table[i].name);
-
- if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0)
- continue;
-
- checksum_info_table[i].supported = true;
- }
+ for (i = 0; checksum_info_table[i].list; i++)
+ for (j = 0; j < checksum_info_table[i].n; j++) {
+ struct checksum_info *info;
- close(sk);
-}
+ info = &checksum_info_table[i].list[j];
+ if (!info->name)
+ continue;
-static inline bool is_supported(const char *alg)
-{
- int i;
+ strcpy((char *) salg.salg_name, info->name);
- for (i = 0; checksum_info_table[i].name; i++) {
- if (strcmp(checksum_info_table[i].name, alg))
- continue;
+ if (bind(sk, (struct sockaddr *) &salg,
+ sizeof(salg)) < 0)
+ continue;
- return checksum_info_table[i].supported;
- }
+ info->supported = true;
+ }
- return false;
+ close(sk);
}
LIB_EXPORT bool l_checksum_is_supported(enum l_checksum_type type,
bool check_hmac)
{
- const char *name;
- char hmac[sizeof(((struct sockaddr_alg *)0)->salg_name)];
+ const struct checksum_info *list;
init_supported();
- name = checksum_type_to_name(type);
- if (!name)
- return false;
+ if (!check_hmac) {
+ if (!is_valid_index(checksum_algs, type))
+ return false;
- if (!is_supported(name))
- return false;
+ list = checksum_algs;
+ } else {
+ if (!is_valid_index(checksum_hmac_algs, type))
+ return false;
- if (!check_hmac)
- return true;
+ list = checksum_hmac_algs;
+ }
- snprintf(hmac, sizeof(hmac) - 1, "hmac(%s)", name);
- return is_supported(hmac);
+ return list[type].supported;
}
LIB_EXPORT bool l_checksum_cmac_aes_supported()
{
init_supported();
- return is_supported("cmac(aes)");
+ return checksum_cmac_aes_alg.supported;
}
LIB_EXPORT ssize_t l_checksum_digest_length(enum l_checksum_type type)
{
- const char *name;
- int i;
-
- name = checksum_type_to_name(type);
- if (!name)
- return -EINVAL;
-
- for (i = 0; checksum_info_table[i].name; i++) {
- if (!strcmp(checksum_info_table[i].name, name))
- return checksum_info_table[i].digest_len;
- }
-
- return 0;
+ return is_valid_index(checksum_algs, type) ?
+ checksum_algs[type].digest_len : 0;
}
--
2.19.1
3 years, 5 months