summaryrefslogtreecommitdiffstats
path: root/src/libsystemd-network/network-common.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libsystemd-network/network-common.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/libsystemd-network/network-common.c b/src/libsystemd-network/network-common.c
new file mode 100644
index 0000000..b639e9c
--- /dev/null
+++ b/src/libsystemd-network/network-common.c
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "env-util.h"
+#include "format-util.h"
+#include "network-common.h"
+#include "socket-util.h"
+#include "unaligned.h"
+
+int get_ifname(int ifindex, char **ifname) {
+ assert(ifname);
+
+ /* This sets ifname only when it is not set yet. */
+
+ if (*ifname)
+ return 0;
+
+ return format_ifname_alloc(ifindex, ifname);
+}
+
+usec_t unaligned_be32_sec_to_usec(const void *p, bool max_as_infinity) {
+ uint32_t s = unaligned_read_be32(ASSERT_PTR(p));
+
+ if (s == UINT32_MAX && max_as_infinity)
+ return USEC_INFINITY;
+
+ return s * USEC_PER_SEC;
+}
+
+usec_t be32_sec_to_usec(be32_t t, bool max_as_infinity) {
+ uint32_t s = be32toh(t);
+
+ if (s == UINT32_MAX && max_as_infinity)
+ return USEC_INFINITY;
+
+ return s * USEC_PER_SEC;
+}
+
+usec_t be32_msec_to_usec(be32_t t, bool max_as_infinity) {
+ uint32_t s = be32toh(t);
+
+ if (s == UINT32_MAX && max_as_infinity)
+ return USEC_INFINITY;
+
+ return s * USEC_PER_MSEC;
+}
+
+usec_t be16_sec_to_usec(be16_t t, bool max_as_infinity) {
+ uint16_t s = be16toh(t);
+
+ if (s == UINT16_MAX && max_as_infinity)
+ return USEC_INFINITY;
+
+ return s * USEC_PER_SEC;
+}
+
+be32_t usec_to_be32_sec(usec_t t) {
+ if (t == USEC_INFINITY)
+ /* Some settings, e.g. a lifetime of an address, UINT32_MAX is handled as infinity. so let's
+ * map USEC_INFINITY to UINT32_MAX. */
+ return htobe32(UINT32_MAX);
+
+ if (t >= (UINT32_MAX - 1) * USEC_PER_SEC)
+ /* Finite but too large. Let's use the largest (or off-by-one from the largest) finite value. */
+ return htobe32(UINT32_MAX - 1);
+
+ return htobe32((uint32_t) DIV_ROUND_UP(t, USEC_PER_SEC));
+}
+
+be32_t usec_to_be32_msec(usec_t t) {
+ if (t == USEC_INFINITY)
+ return htobe32(UINT32_MAX);
+
+ if (t >= (UINT32_MAX - 1) * USEC_PER_MSEC)
+ return htobe32(UINT32_MAX - 1);
+
+ return htobe32((uint32_t) DIV_ROUND_UP(t, USEC_PER_MSEC));
+}
+
+be16_t usec_to_be16_sec(usec_t t) {
+ if (t == USEC_INFINITY)
+ return htobe16(UINT16_MAX);
+
+ if (t >= (UINT16_MAX - 1) * USEC_PER_SEC)
+ return htobe16(UINT16_MAX - 1);
+
+ return htobe16((uint16_t) DIV_ROUND_UP(t, USEC_PER_SEC));
+}
+
+usec_t time_span_to_stamp(usec_t span, usec_t base) {
+ /* Typically, 0 lifetime (timespan) indicates the corresponding configuration (address or so) must be
+ * dropped. So, when the timespan is zero, here we return 0 rather than 'base'. This makes the caller
+ * easily understand that the configuration needs to be dropped immediately. */
+ if (span == 0)
+ return 0;
+
+ return usec_add(base, span);
+}
+
+bool network_test_mode_enabled(void) {
+ static int test_mode = -1;
+ int r;
+
+ if (test_mode < 0) {
+ r = getenv_bool("SYSTEMD_NETWORK_TEST_MODE");
+ if (r < 0) {
+ if (r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_NETWORK_TEST_MODE environment variable, ignoring: %m");
+
+ test_mode = false;
+ } else
+ test_mode = r;
+ }
+
+ return test_mode;
+}
+
+triple_timestamp* triple_timestamp_from_cmsg(triple_timestamp *t, struct msghdr *mh) {
+ assert(t);
+ assert(mh);
+
+ struct timeval *tv = CMSG_FIND_AND_COPY_DATA(mh, SOL_SOCKET, SCM_TIMESTAMP, struct timeval);
+ if (tv)
+ return triple_timestamp_from_realtime(t, timeval_load(tv));
+
+ return triple_timestamp_now(t);
+}