summaryrefslogtreecommitdiff
path: root/xutils.c
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
committerDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
commit1a9fbac03c684f29cff9ac44875bd9504a89f54e (patch)
tree1b2e40dbe5dc1899ef5b62c4325c9b94c9c450fc /xutils.c
all: import netsniff-ng 0.5.8-rc0 source
We decided to get rid of the old Git history and start a new one for several reasons: *) Allow / enforce only high-quality commits (which was not the case for many commits in the history), have a policy that is more close to the one from the Linux kernel. With high quality commits, we mean code that is logically split into commits and commit messages that are signed-off and have a proper subject and message body. We do not allow automatic Github merges anymore, since they are total bullshit. However, we will either cherry-pick your patches or pull them manually. *) The old archive was about ~27MB for no particular good reason. This basically derived from the bad decision that also some PDF files where stored there. From this moment onwards, no binary objects are allowed to be stored in this repository anymore. The old archive is not wiped away from the Internet. You will still be able to find it, e.g. on git.cryptoism.org etc. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'xutils.c')
-rw-r--r--xutils.c1024
1 files changed, 1024 insertions, 0 deletions
diff --git a/xutils.c b/xutils.c
new file mode 100644
index 0000000..7a12d1e
--- /dev/null
+++ b/xutils.c
@@ -0,0 +1,1024 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Copyright 2009, 2010 Daniel Borkmann.
+ * Copyright 2009, 2010 Emmanuel Roullit.
+ * Copyright 2010 Marek Polacek.
+ * Subject to the GPL, version 2.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <time.h>
+#include <sched.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/epoll.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+#include <linux/if.h>
+#include <linux/socket.h>
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/sockios.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#include "die.h"
+#include "xutils.h"
+#include "ring.h"
+#include "built_in.h"
+
+#define IOPRIO_CLASS_SHIFT 13
+
+enum {
+ ioprio_class_none,
+ ioprio_class_rt,
+ ioprio_class_be,
+ ioprio_class_idle,
+};
+
+enum {
+ ioprio_who_process = 1,
+ ioprio_who_pgrp,
+ ioprio_who_user,
+};
+
+enum {
+ sock_rmem_max = 0,
+ sock_rmem_def,
+ sock_wmem_max,
+ sock_wmem_def,
+};
+
+#define SMEM_SUG_MAX 104857600
+#define SMEM_SUG_DEF 4194304
+
+static const char *const to_prio[] = {
+ "none",
+ "realtime",
+ "best-effort",
+ "idle",
+};
+
+static const char *const sock_mem[] = {
+ "/proc/sys/net/core/rmem_max",
+ "/proc/sys/net/core/rmem_default",
+ "/proc/sys/net/core/wmem_max",
+ "/proc/sys/net/core/wmem_default",
+};
+
+int af_socket(int af)
+{
+ int sock;
+
+ if (unlikely(af != AF_INET && af != AF_INET6))
+ panic("Wrong AF socket type!\n");
+
+ sock = socket(af, SOCK_DGRAM, 0);
+ if (unlikely(sock < 0))
+ panic("Creation AF socket failed!\n");
+
+ return sock;
+}
+
+int pf_socket(void)
+{
+ int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (unlikely(sock < 0))
+ panic("Creation of PF socket failed!\n");
+
+ return sock;
+}
+
+void set_sock_prio(int fd, int prio)
+{
+ int val = prio;
+ setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val));
+}
+
+void set_udp_cork(int fd)
+{
+ int state = 1;
+ setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
+}
+
+void set_udp_uncork(int fd)
+{
+ int state = 0;
+ setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
+}
+
+void set_tcp_cork(int fd)
+{
+ int state = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
+}
+
+void set_tcp_uncork(int fd)
+{
+ int state = 0;
+ setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
+}
+
+void set_sock_cork(int fd, int udp)
+{
+ if (!!udp)
+ set_udp_cork(fd);
+ else
+ set_tcp_cork(fd);
+}
+
+void set_sock_uncork(int fd, int udp)
+{
+ if (!!udp)
+ set_udp_uncork(fd);
+ else
+ set_tcp_uncork(fd);
+}
+
+int set_nonblocking(int fd)
+{
+ int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
+ if (unlikely(ret < 0))
+ panic("Cannot fcntl!\n");
+
+ return 0;
+}
+
+int set_nonblocking_sloppy(int fd)
+{
+ return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
+}
+
+void set_socket_keepalive(int fd)
+{
+ int one = 1;
+ setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
+}
+
+void set_tcp_nodelay(int fd)
+{
+ int one = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
+}
+
+int set_ipv6_only(int fd)
+{
+ int one = 1;
+ return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
+}
+
+int set_reuseaddr(int fd)
+{
+ int ret, one = 1;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ if (unlikely(ret < 0))
+ panic("Cannot reuse addr!\n");
+
+ return 0;
+}
+
+void set_mtu_disc_dont(int fd)
+{
+ int mtu = IP_PMTUDISC_DONT;
+ setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
+}
+
+void set_epoll_descriptor(int fd_epoll, int action, int fd_toadd, int events)
+{
+ int ret;
+ struct epoll_event ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.events = events;
+ ev.data.fd = fd_toadd;
+
+ ret = epoll_ctl(fd_epoll, action, fd_toadd, &ev);
+ if (ret < 0)
+ panic("Cannot add socket for epoll!\n");
+}
+
+int set_epoll_descriptor2(int fd_epoll, int action, int fd_toadd, int events)
+{
+ struct epoll_event ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.events = events;
+ ev.data.fd = fd_toadd;
+
+ return epoll_ctl(fd_epoll, action, fd_toadd, &ev);
+}
+
+u32 wireless_bitrate(const char *ifname)
+{
+ int sock, ret, rate_in_mbit;
+ struct iwreq iwr;
+
+ sock = af_socket(AF_INET);
+
+ memset(&iwr, 0, sizeof(iwr));
+ strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
+
+ ret = ioctl(sock, SIOCGIWRATE, &iwr);
+ if (!ret)
+ rate_in_mbit = iwr.u.bitrate.value / 1000000;
+ else
+ rate_in_mbit = 0;
+
+ close(sock);
+
+ return rate_in_mbit;
+}
+
+void drop_privileges(bool enforce, uid_t uid, gid_t gid)
+{
+ if (enforce) {
+ if (uid == getuid())
+ panic("Uid cannot be the same as the current user!\n");
+ if (gid == getgid())
+ panic("Gid cannot be the same as the current user!\n");
+ }
+ if (setgid(gid) != 0)
+ panic("Unable to drop group privileges: %s!\n", strerror(errno));
+ if (setuid(uid) != 0)
+ panic("Unable to drop user privileges: %s!\n", strerror(errno));
+}
+
+int get_system_socket_mem(int which)
+{
+ int fd, val = -1;
+ ssize_t ret;
+ const char *file = sock_mem[which];
+ char buff[64];
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0)
+ return val;
+
+ ret = read(fd, buff, sizeof(buff));
+ if (ret > 0)
+ val = atoi(buff);
+
+ close(fd);
+ return val;
+}
+
+void set_system_socket_mem(int which, int val)
+{
+ int fd;
+ const char *file = sock_mem[which];
+ ssize_t ret;
+ char buff[64];
+
+ fd = open(file, O_WRONLY);
+ if (fd < 0)
+ return;
+
+ memset(buff, 0, sizeof(buff));
+ slprintf(buff, sizeof(buff), "%d", val);
+
+ ret = write(fd, buff, strlen(buff));
+ ret = ret;
+
+ close(fd);
+}
+
+int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
+{
+ int ret, sock;
+ struct iwreq iwr;
+
+ sock = af_socket(AF_INET);
+
+ memset(&iwr, 0, sizeof(iwr));
+ strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
+
+ iwr.u.data.pointer = (caddr_t) stats;
+ iwr.u.data.length = sizeof(*stats);
+ iwr.u.data.flags = 1;
+
+ ret = ioctl(sock, SIOCGIWSTATS, &iwr);
+
+ close(sock);
+
+ return ret;
+}
+
+int wireless_rangemax_sigqual(const char *ifname)
+{
+ int ret, sock, sigqual;
+ struct iwreq iwr;
+ struct iw_range iwrange;
+
+ sock = af_socket(AF_INET);
+
+ memset(&iwrange, 0, sizeof(iwrange));
+
+ memset(&iwr, 0, sizeof(iwr));
+ strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
+
+ iwr.u.data.pointer = (caddr_t) &iwrange;
+ iwr.u.data.length = sizeof(iwrange);
+ iwr.u.data.flags = 0;
+
+ ret = ioctl(sock, SIOCGIWRANGE, &iwr);
+ if (!ret)
+ sigqual = iwrange.max_qual.qual;
+ else
+ sigqual = 0;
+
+ close(sock);
+
+ return sigqual;
+}
+
+u32 ethtool_bitrate(const char *ifname)
+{
+ int ret, sock, bitrate;
+ struct ifreq ifr;
+ struct ethtool_cmd ecmd;
+
+ sock = af_socket(AF_INET);
+
+ memset(&ecmd, 0, sizeof(ecmd));
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ecmd.cmd = ETHTOOL_GSET;
+ ifr.ifr_data = (char *) &ecmd;
+
+ ret = ioctl(sock, SIOCETHTOOL, &ifr);
+ if (ret) {
+ bitrate = 0;
+ goto out;
+ }
+
+ switch (ecmd.speed) {
+ case SPEED_10:
+ case SPEED_100:
+ case SPEED_1000:
+ case SPEED_2500:
+ case SPEED_10000:
+ bitrate = ecmd.speed;
+ break;
+ default:
+ bitrate = 0;
+ break;
+ };
+out:
+ close(sock);
+
+ return bitrate;
+}
+
+int ethtool_link(const char *ifname)
+{
+ int ret, sock;
+ struct ifreq ifr;
+ struct ethtool_value ecmd;
+
+ sock = af_socket(AF_INET);
+
+ memset(&ecmd, 0, sizeof(ecmd));
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ecmd.cmd = ETHTOOL_GLINK;
+ ifr.ifr_data = (char *) &ecmd;
+
+ ret = ioctl(sock, SIOCETHTOOL, &ifr);
+ if (ret)
+ ret = -EINVAL;
+ else
+ ret = !!ecmd.data;
+
+ close(sock);
+ return ret;
+}
+
+int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
+{
+ int ret, sock;
+ struct ifreq ifr;
+
+ sock = af_socket(AF_INET);
+
+ memset(drvinf, 0, sizeof(*drvinf));
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ drvinf->cmd = ETHTOOL_GDRVINFO;
+ ifr.ifr_data = (char *) drvinf;
+
+ ret = ioctl(sock, SIOCETHTOOL, &ifr);
+
+ close(sock);
+
+ return ret;
+}
+
+u32 device_bitrate(const char *ifname)
+{
+ u32 speed_c, speed_w;
+
+ speed_c = ethtool_bitrate(ifname);
+ speed_w = wireless_bitrate(ifname);
+
+ return (speed_c == 0 ? speed_w : speed_c);
+}
+
+int device_ifindex(const char *ifname)
+{
+ int ret, sock, index;
+ struct ifreq ifr;
+
+ if (!strncmp("any", ifname, strlen("any")))
+ return 0;
+
+ sock = af_socket(AF_INET);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ret = ioctl(sock, SIOCGIFINDEX, &ifr);
+ if (!ret)
+ index = ifr.ifr_ifindex;
+ else
+ index = -1;
+
+ close(sock);
+
+ return index;
+}
+
+static int __device_address6(const char *ifname, struct sockaddr_storage *ss)
+{
+ int ret, family, found = -EINVAL;
+ struct ifaddrs *ifaddr, *ifa;
+
+ ret = getifaddrs(&ifaddr);
+ if (ret < 0)
+ panic("Cannot get device addresses for IPv6!\n");
+
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ family = ifa->ifa_addr->sa_family;
+ if (family != AF_INET6)
+ continue;
+ if (strcmp(ifa->ifa_name, ifname))
+ continue;
+
+ memcpy(ss, ifa->ifa_addr, sizeof(*ss));
+ found = 0;
+ break;
+ }
+
+ freeifaddrs(ifaddr);
+ return found;
+}
+
+int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
+{
+ int ret, sock;
+ struct ifreq ifr;
+
+ if (!ss)
+ return -EINVAL;
+ if (!strncmp("any", ifname, strlen("any")))
+ return -EINVAL;
+ if (af == AF_INET6)
+ return __device_address6(ifname, ss);
+
+ sock = af_socket(af);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ifr.ifr_addr.sa_family = af;
+
+ ret = ioctl(sock, SIOCGIFADDR, &ifr);
+ if (!ret)
+ memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
+
+ close(sock);
+
+ return ret;
+}
+
+int device_mtu(const char *ifname)
+{
+ int ret, sock, mtu;
+ struct ifreq ifr;
+
+ sock = af_socket(AF_INET);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ret = ioctl(sock, SIOCGIFMTU, &ifr);
+ if (!ret)
+ mtu = ifr.ifr_mtu;
+ else
+ mtu = 0;
+
+ close(sock);
+
+ return mtu;
+}
+
+short device_get_flags(const char *ifname)
+{
+ /* Really, it's short! Look at struct ifreq */
+ short flags;
+ int ret, sock;
+ struct ifreq ifr;
+
+ sock = af_socket(AF_INET);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
+ if (!ret)
+ flags = ifr.ifr_flags;
+ else
+ flags = 0;
+
+ close(sock);
+
+ return flags;
+}
+
+void device_set_flags(const char *ifname, const short flags)
+{
+ int ret, sock;
+ struct ifreq ifr;
+
+ sock = af_socket(AF_INET);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ ifr.ifr_flags = flags;
+
+ ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
+ if (ret < 0)
+ panic("Cannot set NIC flags!\n");
+
+ close(sock);
+}
+
+int device_irq_number(const char *ifname)
+{
+ /*
+ * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
+ * supported anymore, we need to grab them from procfs
+ */
+ int irq = 0;
+ char *buffp;
+ char buff[512];
+ char sysname[512];
+ FILE *fp;
+
+ if (!strncmp("lo", ifname, strlen("lo")))
+ return 0;
+
+ fp = fopen("/proc/interrupts", "r");
+ if (!fp)
+ panic("Cannot open /proc/interrupts!\n");
+
+ memset(buff, 0, sizeof(buff));
+ while (fgets(buff, sizeof(buff), fp) != NULL) {
+ buff[sizeof(buff) - 1] = 0;
+
+ if (strstr(buff, ifname) == NULL)
+ continue;
+
+ buffp = buff;
+ while (*buffp != ':')
+ buffp++;
+ *buffp = 0;
+ irq = atoi(buff);
+
+ memset(buff, 0, sizeof(buff));
+ }
+
+ fclose(fp);
+
+ if (irq != 0)
+ return irq;
+ /*
+ * Try sysfs as fallback. Probably wireless devices will be found
+ * here. We return silently if it fails ...
+ */
+ slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
+ ifname);
+
+ fp = fopen(sysname, "r");
+ if (!fp)
+ return -ENOENT;
+
+ memset(buff, 0, sizeof(buff));
+ if(fgets(buff, sizeof(buff), fp) != NULL) {
+ buff[sizeof(buff) - 1] = 0;
+ irq = atoi(buff);
+ }
+
+ fclose(fp);
+
+ return irq;
+}
+
+int device_set_irq_affinity_list(int irq, unsigned long from, unsigned long to)
+{
+ int ret, fd;
+ char file[256], list[64];
+
+ slprintf(file, sizeof(file), "/proc/irq/%d/smp_affinity_list", irq);
+ slprintf(list, sizeof(list), "%lu-%lu\n", from, to);
+
+ fd = open(file, O_WRONLY);
+ if (fd < 0)
+ return -ENOENT;
+
+ ret = write(fd, list, strlen(list));
+
+ close(fd);
+ return ret;
+}
+
+int device_bind_irq_to_cpu(int irq, int cpu)
+{
+ int ret;
+ char buff[256];
+ char file[256];
+ FILE *fp;
+
+ /* Note: first CPU begins with CPU 0 */
+ if (irq < 0 || cpu < 0)
+ return -EINVAL;
+
+ memset(file, 0, sizeof(file));
+ memset(buff, 0, sizeof(buff));
+
+ /* smp_affinity starts counting with CPU 1, 2, ... */
+ cpu = cpu + 1;
+ sprintf(file, "/proc/irq/%d/smp_affinity", irq);
+
+ fp = fopen(file, "w");
+ if (!fp)
+ return -ENOENT;
+
+ sprintf(buff, "%d", cpu);
+ ret = fwrite(buff, sizeof(buff), 1, fp);
+
+ fclose(fp);
+ return (ret > 0 ? 0 : ret);
+}
+
+void sock_print_net_stats(int sock, unsigned long skipped)
+{
+ int ret;
+ struct tpacket_stats kstats;
+
+ socklen_t slen = sizeof(kstats);
+
+ memset(&kstats, 0, sizeof(kstats));
+ ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
+ if (ret > -1) {
+ uint64_t packets = kstats.tp_packets;
+ uint64_t drops = kstats.tp_drops;
+
+ printf("\r%12ld packets incoming\n", packets);
+ printf("\r%12ld packets passed filter\n", packets - drops - skipped);
+ printf("\r%12ld packets failed filter (out of space)\n", drops + skipped);
+ if (kstats.tp_packets > 0)
+ printf("\r%12.4lf%\% packet droprate\n", (1.0 * drops / packets) * 100.0);
+ }
+}
+
+void register_signal(int signal, void (*handler)(int))
+{
+ sigset_t block_mask;
+ struct sigaction saction;
+
+ sigfillset(&block_mask);
+
+ saction.sa_handler = handler;
+ saction.sa_mask = block_mask;
+ saction.sa_flags = SA_RESTART;
+
+ sigaction(signal, &saction, NULL);
+}
+
+void register_signal_f(int signal, void (*handler)(int), int flags)
+{
+ sigset_t block_mask;
+ struct sigaction saction;
+
+ sigfillset(&block_mask);
+
+ saction.sa_handler = handler;
+ saction.sa_mask = block_mask;
+ saction.sa_flags = flags;
+
+ sigaction(signal, &saction, NULL);
+}
+
+short enter_promiscuous_mode(char *ifname)
+{
+ short ifflags;
+
+ if (!strncmp("any", ifname, strlen("any")))
+ return 0;
+
+ ifflags = device_get_flags(ifname);
+ device_set_flags(ifname, ifflags | IFF_PROMISC);
+
+ return ifflags;
+}
+
+void leave_promiscuous_mode(char *ifname, short oldflags)
+{
+ if (!strncmp("any", ifname, strlen("any")))
+ return;
+
+ device_set_flags(ifname, oldflags);
+}
+
+int device_up_and_running(char *ifname)
+{
+ if (!ifname)
+ return -EINVAL;
+ if (!strncmp("any", ifname, strlen("any")))
+ return 1;
+
+ return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING);
+}
+
+void cpu_affinity(int cpu)
+{
+ int ret;
+ cpu_set_t cpu_bitmask;
+
+ CPU_ZERO(&cpu_bitmask);
+ CPU_SET(cpu, &cpu_bitmask);
+
+ ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask),
+ &cpu_bitmask);
+ if (ret)
+ panic("Can't set this cpu affinity!\n");
+}
+
+int set_proc_prio(int priority)
+{
+ int ret = setpriority(PRIO_PROCESS, getpid(), priority);
+ if (ret)
+ panic("Can't set nice val to %i!\n", priority);
+
+ return 0;
+}
+
+int set_sched_status(int policy, int priority)
+{
+ int ret, min_prio, max_prio;
+ struct sched_param sp;
+
+ max_prio = sched_get_priority_max(policy);
+ min_prio = sched_get_priority_min(policy);
+
+ if (max_prio == -1 || min_prio == -1)
+ printf("Cannot determine scheduler prio limits!\n");
+ else if (priority < min_prio)
+ priority = min_prio;
+ else if (priority > max_prio)
+ priority = max_prio;
+
+ memset(&sp, 0, sizeof(sp));
+ sp.sched_priority = priority;
+
+ ret = sched_setscheduler(getpid(), policy, &sp);
+ if (ret) {
+ printf("Cannot set scheduler policy!\n");
+ return -EINVAL;
+ }
+
+ ret = sched_setparam(getpid(), &sp);
+ if (ret) {
+ printf("Cannot set scheduler prio!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int ioprio_set(int which, int who, int ioprio)
+{
+ return syscall(SYS_ioprio_set, which, who, ioprio);
+}
+
+static inline int ioprio_get(int which, int who)
+{
+ return syscall(SYS_ioprio_get, which, who);
+}
+
+static void ioprio_setpid(pid_t pid, int ioprio, int ioclass)
+{
+ int ret = ioprio_set(ioprio_who_process, pid,
+ ioprio | ioclass << IOPRIO_CLASS_SHIFT);
+ if (ret < 0)
+ panic("Failed to set io prio for pid!\n");
+}
+
+void ioprio_print(void)
+{
+ int ioprio = ioprio_get(ioprio_who_process, getpid());
+ if (ioprio < 0)
+ panic("Failed to fetch io prio for pid!\n");
+ else {
+ int ioclass = ioprio >> IOPRIO_CLASS_SHIFT;
+ if (ioclass != ioprio_class_idle) {
+ ioprio &= 0xff;
+ printf("%s: prio %d\n", to_prio[ioclass], ioprio);
+ } else
+ printf("%s\n", to_prio[ioclass]);
+ }
+}
+
+void set_ioprio_rt(void)
+{
+ ioprio_setpid(getpid(), 4, ioprio_class_rt);
+}
+
+void set_ioprio_be(void)
+{
+ ioprio_setpid(getpid(), 4, ioprio_class_be);
+}
+
+void xlockme(void)
+{
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
+ panic("Cannot lock pages!\n");
+}
+
+void xunlockme(void)
+{
+ munlockall();
+}
+
+size_t strlcpy(char *dest, const char *src, size_t size)
+{
+ size_t ret = strlen(src);
+
+ if (size) {
+ size_t len = (ret >= size) ? size - 1 : ret;
+
+ memcpy(dest, src, len);
+ dest[len] = '\0';
+ }
+
+ return ret;
+}
+
+static inline int vslprintf(char *dst, size_t size, const char *fmt, va_list ap)
+{
+ int ret;
+
+ ret = vsnprintf(dst, size, fmt, ap);
+ dst[size - 1] = '\0';
+
+ return ret;
+}
+
+int slprintf(char *dst, size_t size, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vslprintf(dst, size, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int slprintf_nocheck(char *dst, size_t size, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vslprintf(dst, size, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+noinline void *xmemset(void *s, int c, size_t n)
+{
+ size_t i;
+ uint8_t *ptr = s;
+
+ for (i = 0; i < n; ++i)
+ ptr[i] = (uint8_t) c;
+
+ return ptr;
+}
+
+char *strtrim_right(char *p, char c)
+{
+ char *end;
+ size_t len;
+
+ len = strlen(p);
+ while (*p && len) {
+ end = p + len - 1;
+ if (c == *end)
+ *end = 0;
+ else
+ break;
+ len = strlen(p);
+ }
+
+ return p;
+}
+
+int get_default_sched_policy(void)
+{
+ return SCHED_FIFO;
+}
+
+int get_default_sched_prio(void)
+{
+ return sched_get_priority_max(get_default_sched_policy());
+}
+
+int get_number_cpus(void)
+{
+ return sysconf(_SC_NPROCESSORS_CONF);
+}
+
+int get_number_cpus_online(void)
+{
+ return sysconf(_SC_NPROCESSORS_ONLN);
+}
+
+int get_default_proc_prio(void)
+{
+ return -20;
+}
+
+void set_system_socket_memory(int *vals, size_t len)
+{
+ bug_on(len != 4);
+
+ if ((vals[0] = get_system_socket_mem(sock_rmem_max)) < SMEM_SUG_MAX)
+ set_system_socket_mem(sock_rmem_max, SMEM_SUG_MAX);
+ if ((vals[1] = get_system_socket_mem(sock_rmem_def)) < SMEM_SUG_DEF)
+ set_system_socket_mem(sock_rmem_def, SMEM_SUG_DEF);
+ if ((vals[2] = get_system_socket_mem(sock_wmem_max)) < SMEM_SUG_MAX)
+ set_system_socket_mem(sock_wmem_max, SMEM_SUG_MAX);
+ if ((vals[3] = get_system_socket_mem(sock_wmem_def)) < SMEM_SUG_DEF)
+ set_system_socket_mem(sock_wmem_def, SMEM_SUG_DEF);
+}
+
+void reset_system_socket_memory(int *vals, size_t len)
+{
+ bug_on(len != 4);
+
+ set_system_socket_mem(sock_rmem_max, vals[0]);
+ set_system_socket_mem(sock_rmem_def, vals[1]);
+ set_system_socket_mem(sock_wmem_max, vals[2]);
+ set_system_socket_mem(sock_wmem_def, vals[3]);
+}
+
+void set_itimer_interval_value(struct itimerval *itimer, unsigned long sec,
+ unsigned long usec)
+{
+ itimer->it_interval.tv_sec = sec;
+ itimer->it_interval.tv_usec = usec;
+
+ itimer->it_value.tv_sec = sec;
+ itimer->it_value.tv_usec = usec;
+}