161 lines
4.2 KiB
C
161 lines
4.2 KiB
C
#include <netinet/in.h>
|
|
#include <pthread.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "interface.h"
|
|
#include "parsing.h"
|
|
#include "scan.h"
|
|
#include "thread.h"
|
|
|
|
bool g_start = false;
|
|
pthread_mutex_t g_start_mtx;
|
|
pthread_mutex_t g_getservent;
|
|
|
|
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 scan scan_data = {
|
|
.dest_addr = thread_data->dest_addr,
|
|
.host = &thread_data->host,
|
|
.port_start = thread_data->port_start,
|
|
.type = thread_data->type,
|
|
.max_retries = thread_data->max_retries,
|
|
.ttl = thread_data->ttl,
|
|
};
|
|
|
|
for (uint16_t port = thread_data->port_start;
|
|
port <= thread_data->port_end; port++) {
|
|
scan_data.port = port;
|
|
scan_data.response = &thread_data->responses[port - 1];
|
|
scan_data.response->port = port;
|
|
if (scan(&scan_data)) {
|
|
free(p_data);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
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 nb_threads)
|
|
{
|
|
struct thread *threads = malloc(sizeof(struct thread) * nb_threads);
|
|
if (!threads) {
|
|
dprintf(2, "ft_nmap: allocation of threads failed\n");
|
|
return NULL;
|
|
}
|
|
for (uint8_t i = 0; i < nb_threads; i++) {
|
|
memcpy(&threads[i].host, host, sizeof(struct host));
|
|
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;
|
|
char *max_retries = get_option_arg(options, FL_MAXRETRIES);
|
|
threads[i].max_retries = max_retries ? atoi(max_retries) : 1;
|
|
char *ttl = get_option_arg(options, FL_TTL);
|
|
threads[i].ttl = ttl ? atoi(ttl) : 48;
|
|
}
|
|
|
|
return threads;
|
|
error:
|
|
free(threads);
|
|
return NULL;
|
|
}
|
|
|
|
int create_threads(const struct option_lst *options, char *ip_addr,
|
|
struct response *responses)
|
|
{
|
|
struct host host;
|
|
if (get_interface_name(&host) < 0)
|
|
return -1;
|
|
|
|
uint16_t port_start = 1;
|
|
uint16_t port_end = 1024;
|
|
if (option_isset(options, FL_FAST))
|
|
port_end = 128;
|
|
const char *ports = get_option_arg(options, FL_PORTS);
|
|
if (parse_ports(ports, &port_start, &port_end) < 0)
|
|
return -1;
|
|
|
|
const char *nb_threads_str = get_option_arg(options, FL_SPEEDUP);
|
|
if (!nb_threads_str) {
|
|
struct thread *thread_data =
|
|
init_threads_data(options, ip_addr, &host, responses, 1);
|
|
g_start = true;
|
|
routine(thread_data);
|
|
free(thread_data);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t nb_threads = atoi(nb_threads_str);
|
|
if (port_end - port_start + 1 < nb_threads) {
|
|
dprintf(2, "ft_nmap: number of threads to use must be superior "
|
|
"or equals to the ports range\n");
|
|
return -1;
|
|
}
|
|
|
|
struct thread *threads_data =
|
|
init_threads_data(options, ip_addr, &host, responses, nb_threads);
|
|
if (!threads_data)
|
|
return -1;
|
|
pthread_t *threads = malloc(sizeof(pthread_t) * nb_threads);
|
|
if (!threads) {
|
|
free(threads_data);
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_init(&g_start_mtx, NULL);
|
|
pthread_mutex_init(&g_getservent, NULL);
|
|
|
|
const uint16_t ports_per_thread =
|
|
(port_end - port_start + 1) / nb_threads;
|
|
uint16_t remaining_ports = (port_end - port_start + 1) % nb_threads;
|
|
for (uint8_t i = 0; i < nb_threads; i++) {
|
|
threads_data[i].port_start = port_start + i * ports_per_thread;
|
|
threads_data[i].port_end = (port_start - 1) +
|
|
(i + 1) * ports_per_thread +
|
|
(remaining_ports ? 1 : 0);
|
|
if (remaining_ports) {
|
|
remaining_ports--;
|
|
port_start++;
|
|
}
|
|
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);
|
|
|
|
for (uint8_t i = 0; i < nb_threads; i++) {
|
|
if (pthread_join(threads[i], NULL)) {
|
|
dprintf(2, "ft_nmap: error during pthread_join()\n");
|
|
return -1;
|
|
}
|
|
}
|
|
free(threads_data);
|
|
free(threads);
|
|
|
|
return 0;
|
|
}
|