feature: multithreading wip
This commit is contained in:
parent
6538a085b9
commit
623b3ad0d7
@ -2,5 +2,6 @@
|
|||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
int dns_lookup(char *ip_addr, char *hostname, struct sockaddr_in *addr_con);
|
int dns_lookup(char *ip_addr, const char *hostname,
|
||||||
|
struct sockaddr_in *addr_con);
|
||||||
int reverse_dns_lookup(char *ip_addr, char *host);
|
int reverse_dns_lookup(char *ip_addr, char *host);
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "scan.h"
|
||||||
|
|
||||||
#define NB_OPTIONS 5
|
#define NB_OPTIONS 5
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -17,4 +21,6 @@ struct option_lst {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct option_lst *parse_options(int ac, char *const *av);
|
struct option_lst *parse_options(int ac, char *const *av);
|
||||||
char *get_option_arg(struct option_lst *options, e_flag flag);
|
const char *get_option_arg(const struct option_lst *options, e_flag flag);
|
||||||
|
int parse_ports(const char *arg, uint16_t *start, uint16_t *end);
|
||||||
|
e_scantype parse_type(const char *arg);
|
||||||
|
@ -11,7 +11,7 @@ typedef enum {
|
|||||||
SCAN_FIN,
|
SCAN_FIN,
|
||||||
SCAN_XMAS,
|
SCAN_XMAS,
|
||||||
SCAN_UDP,
|
SCAN_UDP,
|
||||||
SCAN_TCP,
|
SCAN_ALL,
|
||||||
} e_scantype;
|
} e_scantype;
|
||||||
|
|
||||||
struct scan {
|
struct scan {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
#include "parsing.h"
|
||||||
#include "response.h"
|
#include "response.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
@ -16,3 +17,5 @@ struct thread {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void *routine(void *p_data);
|
void *routine(void *p_data);
|
||||||
|
int create_threads(const struct option_lst *options, char *ip_addr,
|
||||||
|
struct response *responses);
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
int dns_lookup(char *ip_addr, char *hostname, struct sockaddr_in *addr_con)
|
int dns_lookup(char *ip_addr, const char *hostname,
|
||||||
|
struct sockaddr_in *addr_con)
|
||||||
{
|
{
|
||||||
struct hostent *host = gethostbyname2(hostname, AF_INET);
|
struct hostent *host = gethostbyname2(hostname, AF_INET);
|
||||||
if (!host) {
|
if (!host) {
|
||||||
|
19
src/main.c
19
src/main.c
@ -29,7 +29,7 @@ int main(int ac, char **av)
|
|||||||
char ip_addr[INET_ADDRSTRLEN];
|
char ip_addr[INET_ADDRSTRLEN];
|
||||||
struct sockaddr_in addr_con;
|
struct sockaddr_in addr_con;
|
||||||
|
|
||||||
char *host = get_option_arg(options, FL_IP);
|
const char *host = get_option_arg(options, FL_IP);
|
||||||
if (!host) {
|
if (!host) {
|
||||||
dprintf(2, "ft_nmap: address/hostname required\n");
|
dprintf(2, "ft_nmap: address/hostname required\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -41,23 +41,8 @@ int main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct response responses[1024] = {0};
|
struct response responses[1024] = {0};
|
||||||
|
if (create_threads(options, ip_addr, responses) < 0)
|
||||||
struct thread *single_thread = malloc(sizeof(struct thread));
|
|
||||||
if (get_interface_name(&single_thread->host) < 0)
|
|
||||||
return 1;
|
return 1;
|
||||||
single_thread->dest_addr = ip_addr;
|
|
||||||
single_thread->port_start = 21;
|
|
||||||
single_thread->port_end = 1024;
|
|
||||||
single_thread->responses = responses;
|
|
||||||
single_thread->type = SCAN_SYN;
|
|
||||||
if (routine(single_thread) == NULL) {
|
|
||||||
dprintf(2, "ft_nmap: failed to scan ports\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int threads_running = 0;
|
|
||||||
while (threads_running)
|
|
||||||
;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,98 @@
|
|||||||
|
#include <ctype.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "parsing.h"
|
#include "parsing.h"
|
||||||
|
|
||||||
char *get_option_arg(struct option_lst *options, e_flag flag)
|
const char *get_option_arg(const struct option_lst *options, e_flag flag)
|
||||||
{
|
{
|
||||||
if (!options)
|
if (!options)
|
||||||
return 0;
|
return NULL;
|
||||||
for (struct option_lst *it = options; it; it = it->next)
|
for (const struct option_lst *it = options; it; it = it->next)
|
||||||
if (it->flag == flag)
|
if (it->flag == flag)
|
||||||
return it->arg;
|
return it->arg;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
e_scantype parse_type(const char *arg)
|
||||||
|
{
|
||||||
|
const char *types[] = {
|
||||||
|
"SYN", "NULL", "ACK", "FIN", "XMAS", "UDP",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!arg)
|
||||||
|
return SCAN_ALL;
|
||||||
|
for (size_t i = 0; i < 6; i++)
|
||||||
|
if (!strcmp(arg, types[i]))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_ports(const char *arg, uint16_t *p_start, uint16_t *p_end)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
for (; isdigit(arg[i]); i++)
|
||||||
|
;
|
||||||
|
int start = atoi(arg);
|
||||||
|
if (arg[i++] != '-')
|
||||||
|
return -1;
|
||||||
|
int end = atoi(arg + i);
|
||||||
|
for (; isdigit(arg[i]); i++)
|
||||||
|
;
|
||||||
|
if (arg[i])
|
||||||
|
return -1;
|
||||||
|
if (start >= end)
|
||||||
|
return -1;
|
||||||
|
if (end > UINT16_MAX) {
|
||||||
|
dprintf(2,
|
||||||
|
"ft_nmap: invalid argument: '%s': out of range: 0 "
|
||||||
|
"<= value <= %d\n",
|
||||||
|
arg, UINT16_MAX);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*p_start = start;
|
||||||
|
*p_end = end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_arg(e_flag flag, const char *arg)
|
||||||
|
{
|
||||||
|
switch (flag) {
|
||||||
|
case FL_SPEEDUP:
|
||||||
|
for (size_t i = 0; arg[i]; i++)
|
||||||
|
if (!isdigit(arg[i]))
|
||||||
|
return -1;
|
||||||
|
int value = atoi(arg);
|
||||||
|
if (value < 0 || value > 250) {
|
||||||
|
dprintf(2,
|
||||||
|
"ft_nmap: invalid argument: '%s': out "
|
||||||
|
"of range: 0 "
|
||||||
|
"<= value <= 250\n",
|
||||||
|
arg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FL_SCAN:
|
||||||
|
if (!strcmp(arg, "SYN"))
|
||||||
|
break;
|
||||||
|
if (!strcmp(arg, "NULL"))
|
||||||
|
break;
|
||||||
|
if (!strcmp(arg, "ACK"))
|
||||||
|
break;
|
||||||
|
if (!strcmp(arg, "FIN"))
|
||||||
|
break;
|
||||||
|
if (!strcmp(arg, "XMAS"))
|
||||||
|
break;
|
||||||
|
if (!strcmp(arg, "UDP"))
|
||||||
|
break;
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +100,7 @@ static int add_option(struct option_lst **head, e_flag flag, char *arg)
|
|||||||
{
|
{
|
||||||
struct option_lst *new_option = malloc(sizeof(struct option_lst));
|
struct option_lst *new_option = malloc(sizeof(struct option_lst));
|
||||||
if (!new_option) {
|
if (!new_option) {
|
||||||
dprintf(2, "ft_ping: allocation of option failed\n");
|
dprintf(2, "ft_nmap: allocation of option failed\n");
|
||||||
for (struct option_lst *it = *head; it;) {
|
for (struct option_lst *it = *head; it;) {
|
||||||
struct option_lst *tmp = it;
|
struct option_lst *tmp = it;
|
||||||
it = it->next;
|
it = it->next;
|
||||||
@ -64,6 +145,8 @@ struct option_lst *parse_options(int ac, char *const *av)
|
|||||||
break;
|
break;
|
||||||
else if (c)
|
else if (c)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (check_arg(option_index, optarg) < 0)
|
||||||
|
return NULL;
|
||||||
if (add_option(&head, option_index, optarg) < 0)
|
if (add_option(&head, option_index, optarg) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
131
src/thread.c
131
src/thread.c
@ -1,12 +1,33 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "interface.h"
|
||||||
|
#include "parsing.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
|
uint8_t g_nb_threads;
|
||||||
|
bool g_start = false;
|
||||||
|
pthread_mutex_t g_nb_threads_mtx;
|
||||||
|
pthread_mutex_t g_start_mtx;
|
||||||
|
|
||||||
void *routine(void *p_data)
|
void *routine(void *p_data)
|
||||||
{
|
{
|
||||||
|
while (1) {
|
||||||
|
pthread_mutex_lock(&g_start_mtx);
|
||||||
|
bool start = g_start;
|
||||||
|
pthread_mutex_unlock(&g_start_mtx);
|
||||||
|
if (start)
|
||||||
|
break;
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
struct thread *thread_data = (struct thread *)p_data;
|
struct thread *thread_data = (struct thread *)p_data;
|
||||||
struct scan scan_data = {
|
struct scan scan_data = {
|
||||||
.dest_addr = thread_data->dest_addr,
|
.dest_addr = thread_data->dest_addr,
|
||||||
@ -20,11 +41,113 @@ void *routine(void *p_data)
|
|||||||
scan_data.port = port;
|
scan_data.port = port;
|
||||||
scan_data.response =
|
scan_data.response =
|
||||||
&thread_data->responses[port - thread_data->port_start];
|
&thread_data->responses[port - thread_data->port_start];
|
||||||
if (scan(&scan_data))
|
printf("uwu on port %d\n", port);
|
||||||
|
if (scan(&scan_data)) {
|
||||||
|
free(p_data);
|
||||||
return NULL;
|
return NULL;
|
||||||
printf("%d: %s\n", port,
|
}
|
||||||
scan_data.response->state == 1 ? "OPEN" : "CLOSED");
|
printf("%d has state: %d\n", port, scan_data.response->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return p_data;
|
pthread_mutex_lock(&g_nb_threads_mtx);
|
||||||
|
g_nb_threads--;
|
||||||
|
pthread_mutex_unlock(&g_nb_threads_mtx);
|
||||||
|
free(p_data);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct thread *init_threads_data(const struct option_lst *options,
|
||||||
|
char *ip_addr, const struct host *host,
|
||||||
|
struct response *responses,
|
||||||
|
uint8_t g_nb_threads)
|
||||||
|
{
|
||||||
|
struct thread *threads = malloc(sizeof(struct thread) * g_nb_threads);
|
||||||
|
if (!threads) {
|
||||||
|
dprintf(2, "ft_nmap: allocation of threads failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < g_nb_threads; i++) {
|
||||||
|
memcpy(&threads[i].host, host, sizeof(struct host));
|
||||||
|
const char *ports = get_option_arg(options, FL_PORTS);
|
||||||
|
if (parse_ports(ports, &threads[i].port_start,
|
||||||
|
&threads[i].port_end) < 0)
|
||||||
|
goto error;
|
||||||
|
threads[i].type = parse_type(get_option_arg(options, FL_SCAN));
|
||||||
|
if (threads[i].type < 0)
|
||||||
|
goto error;
|
||||||
|
threads[i].dest_addr = ip_addr;
|
||||||
|
threads[i].responses = responses;
|
||||||
|
}
|
||||||
|
|
||||||
|
return threads;
|
||||||
|
error:
|
||||||
|
free(threads);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_threads(const struct option_lst *options, char *ip_addr,
|
||||||
|
struct response *responses)
|
||||||
|
{
|
||||||
|
uint16_t port_start, port_end;
|
||||||
|
const char *ports = get_option_arg(options, FL_PORTS);
|
||||||
|
if (parse_ports(ports, &port_start, &port_end) < 0)
|
||||||
|
return -1;
|
||||||
|
struct host host;
|
||||||
|
if (get_interface_name(&host) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const char *arg = get_option_arg(options, FL_SPEEDUP);
|
||||||
|
if (!arg) {
|
||||||
|
struct thread *thread_data =
|
||||||
|
init_threads_data(options, ip_addr, &host, responses, 1);
|
||||||
|
thread_data->port_start = port_start;
|
||||||
|
thread_data->port_end = port_end;
|
||||||
|
routine(thread_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_nb_threads = atoi(arg);
|
||||||
|
struct thread *threads_data =
|
||||||
|
init_threads_data(options, ip_addr, &host, responses, g_nb_threads);
|
||||||
|
if (!threads_data)
|
||||||
|
return -1;
|
||||||
|
pthread_t *threads = malloc(sizeof(pthread_t) * g_nb_threads);
|
||||||
|
if (!threads) {
|
||||||
|
free(threads_data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_init(&g_nb_threads_mtx, NULL);
|
||||||
|
pthread_mutex_init(&g_start_mtx, NULL);
|
||||||
|
|
||||||
|
const uint16_t ports_per_thread =
|
||||||
|
(port_end - port_start) / g_nb_threads;
|
||||||
|
uint16_t remaining_ports = (port_end - port_start) % g_nb_threads;
|
||||||
|
for (uint8_t i = 0; i < g_nb_threads; i++) {
|
||||||
|
threads_data[i].port_start = port_start + i * ports_per_thread;
|
||||||
|
threads_data[i].port_end =
|
||||||
|
port_start + (i + 1) * ports_per_thread;
|
||||||
|
// TODO implement remaining_ports
|
||||||
|
(void)remaining_ports;
|
||||||
|
if (pthread_create(&threads[i], NULL, routine,
|
||||||
|
&threads_data[i])) {
|
||||||
|
dprintf(2, "ft_nmap: error during pthread_create()\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&g_start_mtx);
|
||||||
|
g_start = true;
|
||||||
|
pthread_mutex_unlock(&g_start_mtx);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
pthread_mutex_lock(&g_nb_threads_mtx);
|
||||||
|
bool nb_threads = g_nb_threads;
|
||||||
|
pthread_mutex_unlock(&g_nb_threads_mtx);
|
||||||
|
if (nb_threads == 0)
|
||||||
|
break;
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user