Browse code

Add first version of the project.

Xavier G authored on12/10/2020 20:01:53
Showing2 changed files

1 1
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+# so_priority.so
2
+
3
+Set `SO_PRIORITY` (aka `skb->priority` on Linux) right after each `socket()` call.
4
+
5
+Compile with:
6
+
7
+```
8
+gcc -shared -ldl -fPIC so_priority.c -o so_priority.so
9
+```
10
+
11
+Usage:
12
+
13
+```
14
+SO_PRIORITY_DEBUG=1 SO_PRIORITY_VALUE=6 LD_PRELOAD=/path/to/so_priority.so program arg1 arg2
15
+```
0 16
new file mode 100644
... ...
@@ -0,0 +1,100 @@
1
+/*
2
+	Set SO_PRIORITY right after each socket() call.
3
+	Compile with: gcc -shared -ldl -fPIC so_priority.c -o so_priority.so
4
+	Usage: SO_PRIORITY_DEBUG=1 SO_PRIORITY_VALUE=6 LD_PRELOAD=/path/to/so_priority.so program arg1 arg2
5
+
6
+	(c) 2020 - Xavier Guerrin
7
+	This program is free software. It comes without any warranty, to
8
+	the extent permitted by applicable law. You can redistribute it
9
+	and/or modify it under the terms of the Do What The Fuck You Want
10
+	To Public License, Version 2, as published by Sam Hocevar. See
11
+	http://www.wtfpl.net/ for more details.
12
+*/
13
+
14
+#define _GNU_SOURCE /* RTLD_NEXT */
15
+#include <dlfcn.h> /* dlsym, dlerror */
16
+#include <errno.h> /* errno */
17
+#include <stdio.h> /* dprintf */
18
+#include <stdlib.h> /* atoi, getenv */
19
+#include <string.h> /* strerror */
20
+#include <sys/types.h> /* setsockopt */
21
+#include <sys/socket.h> /* setsockopt */
22
+
23
+#ifndef SOPRIORITY_SO_NAME
24
+#define SOPRIORITY_SO_NAME "so_priority.so"
25
+#endif
26
+#ifndef SOPRIORITY_VALUE_EV
27
+#define SOPRIORITY_VALUE_EV "SO_PRIORITY_VALUE"
28
+#endif
29
+#ifndef SOPRIORITY_DEBUG_EV
30
+#define SOPRIORITY_DEBUG_EV "SO_PRIORITY_DEBUG"
31
+#endif
32
+
33
+typedef int (*socket_function_type)(int, int, int);
34
+ 
35
+/* Pointer to the actual scoket symbol. */
36
+socket_function_type so_priority_socket = NULL;
37
+
38
+/* SO_PRIORITY value to set; can be configured using the SO_PRIORITY_VALUE environment variable. */
39
+int so_priority_value = 0;
40
+/* Debug level; can be configured using the SO_PRIORITY_DEBUG environment variable. */
41
+int so_priority_debug = 0;
42
+int so_priority_known = 0;
43
+
44
+/* Ask the linker to provide the actual "socket" symbol: */
45
+static int so_priority_get_socket() {
46
+	char *error_string;
47
+	so_priority_socket = (socket_function_type)dlsym(RTLD_NEXT, "socket");
48
+	if (!so_priority_socket) {
49
+		error_string = dlerror();
50
+		if (error_string) {
51
+			dprintf(2, "%s: unable to find the actual socket symbol: %s\n", SOPRIORITY_SO_NAME, error_string);
52
+		}
53
+		else {
54
+			dprintf(2, "%s: unable to find the actual socket symbol\n", SOPRIORITY_SO_NAME);
55
+		}
56
+		return 0;
57
+	}
58
+	return 1;
59
+}
60
+
61
+/* Read the priority value from the environment. */
62
+static void so_priority_set_options() {
63
+	char *str;
64
+	str = getenv(SOPRIORITY_VALUE_EV);
65
+	if (str) so_priority_value = atoi(str);
66
+	str = getenv(SOPRIORITY_DEBUG_EV);
67
+	if (str) so_priority_debug = atoi(str);
68
+	so_priority_known = 1;
69
+}
70
+
71
+/* Wrapper around the actual socket() function that sets SO_PRIORITY by calling setsockopt(). */
72
+int socket(int domain, int type, int protocol) {
73
+	int ret, setsockopt_errno, socket_errno, sockfd;
74
+
75
+	if (!so_priority_socket && !so_priority_get_socket()) {
76
+		errno = ENOENT;
77
+		return -1;
78
+	}
79
+	/* Actually call socket(): */
80
+	sockfd = so_priority_socket(domain, type, protocol);
81
+	/* Do not call setsockopt() if socket() failed: */
82
+	if (sockfd < 0) return sockfd;
83
+
84
+	/* Time for the actual work: */
85
+	socket_errno = errno;
86
+
87
+	if (!so_priority_known) so_priority_set_options();
88
+	ret = setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &so_priority_value, sizeof(so_priority_value));
89
+	/* Ignore setsockopt() errors, except for debugging purposes. */
90
+	if (so_priority_debug) {
91
+		setsockopt_errno = errno;
92
+		dprintf(2, "%s: setsockopt(%d, SOL_SOCKET, SO_PRIORITY, %d, %zu) returned %d",
93
+		        SOPRIORITY_SO_NAME, sockfd, so_priority_value, sizeof(so_priority_value), ret);
94
+		if (ret < 0) dprintf(2, "; errno is %d: %s", setsockopt_errno, strerror(setsockopt_errno));
95
+		dprintf(2, "\n");
96
+	}
97
+	
98
+	errno = socket_errno;
99
+	return sockfd;
100
+}