aboutgitcodebugslistschat
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c87
1 files changed, 78 insertions, 9 deletions
diff --git a/util.c b/util.c
index 4beb7c2..a4f2be4 100644
--- a/util.c
+++ b/util.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include <stdbool.h>
#include <linux/errqueue.h>
+#include <linux/in6.h>
#include <getopt.h>
#include "linux_dep.h"
@@ -35,10 +36,14 @@
#include "log.h"
#include "pcap.h"
#include "epoll_ctl.h"
+#include "pasta.h"
#ifdef HAS_GETRANDOM
#include <sys/random.h>
#endif
+/* Zero-filled buffer to pad 802.3 frames, up to 60 (ETH_ZLEN) bytes */
+uint8_t eth_pad[ETH_ZLEN] = { 0 };
+
/**
* sock_l4_() - Create and bind socket to socket address
* @c: Execution context
@@ -552,7 +557,7 @@ void pidfile_write(int fd, pid_t pid)
if (write(fd, pid_buf, n) < 0) {
perror("PID file write");
- _exit(EXIT_FAILURE);
+ passt_exit(EXIT_FAILURE);
}
close(fd);
@@ -589,12 +594,12 @@ int __daemon(int pidfile_fd, int devnull_fd)
if (pid == -1) {
perror("fork");
- _exit(EXIT_FAILURE);
+ passt_exit(EXIT_FAILURE);
}
if (pid) {
pidfile_write(pidfile_fd, pid);
- _exit(EXIT_SUCCESS);
+ passt_exit(EXIT_SUCCESS);
}
if (setsid() < 0 ||
@@ -602,7 +607,7 @@ int __daemon(int pidfile_fd, int devnull_fd)
dup2(devnull_fd, STDOUT_FILENO) < 0 ||
dup2(devnull_fd, STDERR_FILENO) < 0 ||
close(devnull_fd))
- _exit(EXIT_FAILURE);
+ passt_exit(EXIT_FAILURE);
return 0;
}
@@ -611,6 +616,9 @@ int __daemon(int pidfile_fd, int devnull_fd)
* fls() - Find last (most significant) bit set in word
* @x: Word
*
+ * Note: unlike ffs() and other implementations of fls(), notably the one from
+ * the Linux kernel, the starting position is 0 and not 1, that is, fls(1) = 0.
+ *
* Return: position of most significant bit set, starting from 0, -1 if none
*/
int fls(unsigned long x)
@@ -627,6 +635,17 @@ int fls(unsigned long x)
}
/**
+ * ilog2() - Integral part (floor) of binary logarithm (logarithm to the base 2)
+ * @x: Argument
+ *
+ * Return: integral part of binary logarithm of @x, -1 if undefined (if @x is 0)
+ */
+int ilog2(unsigned long x)
+{
+ return fls(x);
+}
+
+/**
* write_file() - Replace contents of file with a string
* @path: File to write
* @buf: String to write
@@ -697,7 +716,7 @@ static ssize_t read_file(const char *path, char *buf, size_t buf_size)
close(fd);
- if (total_read == buf_size) {
+ if (total_read >= buf_size) {
buf[buf_size - 1] = '\0';
return -ENOBUFS;
}
@@ -1141,7 +1160,7 @@ void raw_random(void *buf, size_t buflen)
ret = getrandom((char *)buf + random_read,
buflen - random_read, GRND_RANDOM);
#else
- ret = read(dev_random, (char *)buf + random_read,
+ ret = read(fd, (char *)buf + random_read,
buflen - random_read);
#endif
@@ -1158,7 +1177,7 @@ void raw_random(void *buf, size_t buflen)
}
#ifndef HAS_GETRANDOM
- close(dev_random);
+ close(fd);
#endif
if (random_read < buflen)
@@ -1208,15 +1227,65 @@ void abort_with_msg(const char *fmt, ...)
}
/**
- * fsync_pcap_and_log() - Flush pcap and log files as needed
+ * passt_exit() - Perform vital cleanup and exit
+ *
+ * We don't use exit(3) because on some C library versions it can do unexpected
+ * things that hit our seccomp profile (e.g. futex() calls). This is a bespoke
+ * wrapper around _exit(2) performing just the cleanup that we need.
*
* #syscalls fsync
*/
-void fsync_pcap_and_log(void)
+void passt_exit(int status)
{
+ /* Make sure we don't leave the pcap file truncated */
if (pcap_fd != -1 && fsync(pcap_fd))
warn_perror("Failed to flush pcap file, it might be truncated");
+ /* Make sure we don't leave an incomplete log */
if (log_file != -1)
(void)fsync(log_file);
+
+ /* Make sure we don't leave any messages incomplete */
+ (void)fflush(stderr);
+ (void)fflush(stdout);
+
+ _exit(status);
+}
+
+/**
+ * clamped_scale() - Scale @x from 100% to f% depending on @y's value
+ * @x: Value to scale
+ * @y: Value determining scaling
+ * @lo: Lower bound for @y (start of y-axis slope)
+ * @hi: Upper bound for @y (end of y-axis slope)
+ * @f: Scaling factor, percent (might be less or more than 100)
+ *
+ * Return: @x scaled by @f * linear interpolation of @y between @lo and @hi
+ *
+ * In pictures:
+ *
+ * f % -> ,---- * If @y < lo (for example, @y is y0), return @x
+ * /| |
+ * / | | * If @lo < @y < @hi (for example, @y is y1),
+ * / | | return @x scaled by a factor linearly
+ * (100 + f) / 2 % ->/ | | interpolated between 100% and f% depending on
+ * /| | | @y's position between @lo (100%) and @hi (f%)
+ * / | | |
+ * / | | | * If @y > @hi (for example, @y is y2), return
+ * 100 % -> -----' | | | @x * @f / 100
+ * | | | | |
+ * y0 lo y1 hi y2 Example: @f = 150, @lo = 10, @hi = 20, @y = 15,
+ * @x = 1000
+ * -> interpolated factor is 125%
+ * -> return 1250
+ */
+long clamped_scale(long x, long y, long lo, long hi, long f)
+{
+ if (y < lo)
+ return x;
+
+ if (y > hi)
+ return x * f / 100;
+
+ return x - (x * (y - lo) / (hi - lo)) * (100 - f) / 100;
}