feature: flags -F, --max_retries and --ttl (wip)

This commit is contained in:
0x35c 2025-05-31 16:37:24 +02:00
parent ee2af274d9
commit dbed6dc7cd
6 changed files with 120 additions and 31 deletions

View File

@ -1,18 +1,22 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "scan.h" #include "scan.h"
#define NB_OPTIONS 6
typedef enum { typedef enum {
// long options
FL_HELP, FL_HELP,
FL_PORTS, FL_PORTS,
FL_IP, FL_IP,
FL_FILE, FL_FILE,
FL_SPEEDUP, FL_SPEEDUP,
FL_SCAN, FL_SCAN,
FL_MAXRETRIES,
FL_TTL,
// short options
FL_FAST,
} e_flag; } e_flag;
struct option_lst { struct option_lst {
@ -22,6 +26,7 @@ struct option_lst {
}; };
struct option_lst *parse_options(int ac, char *const *av); struct option_lst *parse_options(int ac, char *const *av);
bool option_isset(const struct option_lst *options, e_flag flag);
char *get_option_arg(const struct option_lst *options, e_flag flag); char *get_option_arg(const struct option_lst *options, e_flag flag);
int parse_ports(const char *arg, uint16_t *start, uint16_t *end); int parse_ports(const char *arg, uint16_t *start, uint16_t *end);
e_scantype parse_type(const char *arg); e_scantype parse_type(const char *arg);

View File

@ -20,6 +20,8 @@ struct scan {
uint16_t port_start; uint16_t port_start;
uint16_t port; uint16_t port;
e_scantype type; e_scantype type;
uint8_t ttl;
uint8_t max_retries;
struct response *response; struct response *response;
}; };

View File

@ -12,6 +12,8 @@ struct thread {
uint16_t port_end; uint16_t port_end;
char *dest_addr; char *dest_addr;
e_scantype type; e_scantype type;
uint8_t max_retries;
uint8_t ttl;
struct host host; struct host host;
struct response *responses; struct response *responses;
}; };

View File

@ -1,5 +1,6 @@
#include <ctype.h> #include <ctype.h>
#include <getopt.h> #include <getopt.h>
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@ -18,6 +19,16 @@ void free_options(struct option_lst *options)
} }
} }
bool option_isset(const struct option_lst *options, e_flag flag)
{
if (!options)
return false;
for (const struct option_lst *it = options; it; it = it->next)
if (it->flag == flag)
return true;
return false;
}
char *get_option_arg(const struct option_lst *options, e_flag flag) char *get_option_arg(const struct option_lst *options, e_flag flag)
{ {
if (!options) if (!options)
@ -45,16 +56,16 @@ e_scantype parse_type(const char *arg)
int parse_ports(const char *arg, uint16_t *p_start, uint16_t *p_end) int parse_ports(const char *arg, uint16_t *p_start, uint16_t *p_end)
{ {
size_t i = 0; size_t i = 0;
if (!arg) { if (!arg)
*p_start = 1; return -1;
*p_end = 1024;
return 0;
}
for (; isdigit(arg[i]); i++) for (; isdigit(arg[i]); i++)
; ;
int start = atoi(arg); int start = atoi(arg);
if (arg[i] == '\0') if (arg[i] == '\0') {
*p_start = start;
*p_end = start;
return 0; return 0;
}
if (arg[i++] != '-') if (arg[i++] != '-')
goto error; goto error;
int end = atoi(arg + i); int end = atoi(arg + i);
@ -82,7 +93,7 @@ error:
static int check_arg(e_flag flag, const char *arg) static int check_arg(e_flag flag, const char *arg)
{ {
switch (flag) { switch (flag) {
case FL_SPEEDUP: case FL_SPEEDUP: {
for (size_t i = 0; arg[i]; i++) for (size_t i = 0; arg[i]; i++)
if (!isdigit(arg[i])) if (!isdigit(arg[i]))
return -1; return -1;
@ -96,6 +107,7 @@ static int check_arg(e_flag flag, const char *arg)
return -1; return -1;
} }
break; break;
}
case FL_SCAN: case FL_SCAN:
if (!strcmp(arg, "SYN")) if (!strcmp(arg, "SYN"))
break; break;
@ -110,6 +122,37 @@ static int check_arg(e_flag flag, const char *arg)
if (!strcmp(arg, "UDP")) if (!strcmp(arg, "UDP"))
break; break;
return -1; return -1;
case FL_TTL: {
int nb = atoi(arg);
if (nb == 0) {
dprintf(2, "ft_nmap: cannot set unicast time-to-live: "
"Invalid argument\n");
return -1;
} else if (nb < 0 || nb > 255) {
dprintf(
2,
"ft_nmap: invalid argument: '%s': out of range: 0 "
"<= value <= 255\n",
arg);
return -1;
}
break;
}
case FL_MAXRETRIES: {
int nb = atoi(arg);
if (nb == 0) {
dprintf(2, "ft_nmap: cannot set max_retries to 0\n");
return -1;
} else if (nb < 0 || nb > 255) {
dprintf(
2,
"ft_nmap: invalid argument: '%s': out of range: 0 "
"<= value <= 255\n",
arg);
return -1;
}
break;
}
default: default:
break; break;
} }
@ -149,23 +192,32 @@ static int add_option(struct option_lst **head, e_flag flag, char *arg)
struct option_lst *parse_options(int ac, char *const *av) struct option_lst *parse_options(int ac, char *const *av)
{ {
struct option_lst *head = NULL; struct option_lst *head = NULL;
const struct option options[NB_OPTIONS] = { const struct option options[] = {
{"help", no_argument, 0, 0}, {"help", no_argument, 0, 0},
{"ports", required_argument, 0, 0}, {"ports", required_argument, 0, 0},
{"ip", required_argument, 0, 0}, {"ip", required_argument, 0, 0},
{"file", required_argument, 0, 0}, {"file", required_argument, 0, 0},
{"speedup", required_argument, 0, 0}, {"speedup", required_argument, 0, 0},
{"scan", required_argument, 0, 0}, {"scan", required_argument, 0, 0},
{"max_retries", required_argument, 0, 0},
{"ttl", required_argument, 0, 0},
}; };
int c; int c;
while (1) { while (1) {
int option_index = 0; int option_index = 0;
c = getopt_long(ac, av, "", options, &option_index); c = getopt_long(ac, av, "F", options, &option_index);
if (c == -1) if (c == -1)
break; break;
else if (c) switch (c) {
case 'F':
add_option(&head, FL_FAST, optarg);
break;
case '?':
return NULL; return NULL;
default:
break;
}
if (check_arg(option_index, optarg) < 0) if (check_arg(option_index, optarg) < 0)
return NULL; return NULL;
if (add_option(&head, option_index, optarg) < 0) if (add_option(&head, option_index, optarg) < 0)

View File

@ -39,8 +39,7 @@ static void dispatch_callback(u_char *user, const struct pcap_pkthdr *h,
} }
} }
static void send_recv_packet(const struct scan *data, int sockfd, static int send_recv_packet(const struct scan *data, int sockfd, pcap_t *handle)
pcap_t *handle)
{ {
send_packet(data, sockfd); send_packet(data, sockfd);
uint8_t timer = 0; uint8_t timer = 0;
@ -49,9 +48,12 @@ static void send_recv_packet(const struct scan *data, int sockfd,
break; break;
usleep(100000); usleep(100000);
} }
if (timer == TIMEOUT * 100)
no_response(data);
pcap_breakloop(handle); pcap_breakloop(handle);
if (timer == TIMEOUT * 100) {
no_response(data);
return 0;
}
return 1;
} }
int scan(struct scan *data) int scan(struct scan *data)
@ -102,11 +104,17 @@ int scan(struct scan *data)
if (data->type == SCAN_ALL) { if (data->type == SCAN_ALL) {
for (e_scantype type = SCAN_NULL; type < SCAN_ALL; type++) { for (e_scantype type = SCAN_NULL; type < SCAN_ALL; type++) {
data->type = type; data->type = type;
send_recv_packet(data, sockfd, handle); for (uint8_t retries = 0; retries < data->max_retries;
retries++)
if (send_recv_packet(data, sockfd, handle))
break;
} }
data->type = SCAN_ALL; data->type = SCAN_ALL;
} else { } else {
send_recv_packet(data, sockfd, handle); for (uint8_t retries = 0; retries < data->max_retries;
retries++)
if (send_recv_packet(data, sockfd, handle))
break;
} }
pcap_close(handle); pcap_close(handle);

View File

@ -33,6 +33,8 @@ void *routine(void *p_data)
.host = &thread_data->host, .host = &thread_data->host,
.port_start = thread_data->port_start, .port_start = thread_data->port_start,
.type = thread_data->type, .type = thread_data->type,
.max_retries = thread_data->max_retries,
.ttl = thread_data->ttl,
}; };
for (uint16_t port = thread_data->port_start; for (uint16_t port = thread_data->port_start;
@ -60,15 +62,26 @@ static struct thread *init_threads_data(const struct option_lst *options,
} }
for (uint8_t i = 0; i < nb_threads; i++) { for (uint8_t i = 0; i < nb_threads; i++) {
memcpy(&threads[i].host, host, sizeof(struct host)); memcpy(&threads[i].host, host, sizeof(struct host));
threads[i].port_start = 1;
threads[i].port_end = 1024;
if (option_isset(options, FL_FAST))
threads[i].port_end = 128;
const char *ports = get_option_arg(options, FL_PORTS); const char *ports = get_option_arg(options, FL_PORTS);
if (parse_ports(ports, &threads[i].port_start, if (parse_ports(ports, &threads[i].port_start,
&threads[i].port_end) < 0) &threads[i].port_end) < 0) {
if (!option_isset(options, FL_FAST))
goto error; goto error;
threads[i].port_end = 128;
}
threads[i].type = parse_type(get_option_arg(options, FL_SCAN)); threads[i].type = parse_type(get_option_arg(options, FL_SCAN));
if (threads[i].type < 0) if (threads[i].type < 0)
goto error; goto error;
threads[i].dest_addr = ip_addr; threads[i].dest_addr = ip_addr;
threads[i].responses = responses; 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; return threads;
@ -80,29 +93,36 @@ error:
int create_threads(const struct option_lst *options, char *ip_addr, int create_threads(const struct option_lst *options, char *ip_addr,
struct response *responses) struct response *responses)
{ {
uint16_t port_start = 0, port_end = 0;
const char *ports = get_option_arg(options, FL_PORTS);
if (parse_ports(ports, &port_start, &port_end) < 0)
return -1;
struct host host; struct host host;
if (get_interface_name(&host) < 0) if (get_interface_name(&host) < 0)
return -1; return -1;
const char *arg = get_option_arg(options, FL_SPEEDUP); uint16_t port_start = 1;
// Launche single thread routine if it's a 1 port scan or if no speedup uint16_t port_end = 1024;
// option was passed const char *ports = get_option_arg(options, FL_PORTS);
if (!arg || !port_end) { if (parse_ports(ports, &port_start, &port_end) < 0) {
if (!option_isset(options, FL_FAST))
return -1;
port_end = 128;
}
const char *nb_threads_str = get_option_arg(options, FL_SPEEDUP);
if (!nb_threads_str) {
struct thread *thread_data = struct thread *thread_data =
init_threads_data(options, ip_addr, &host, responses, 1); init_threads_data(options, ip_addr, &host, responses, 1);
thread_data->port_start = port_start;
thread_data->port_end = port_end;
g_start = true; g_start = true;
routine(thread_data); routine(thread_data);
free(thread_data); free(thread_data);
return 0; return 0;
} }
uint8_t nb_threads = atoi(arg); uint8_t nb_threads = atoi(nb_threads_str);
if (port_end - port_start < 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 = struct thread *threads_data =
init_threads_data(options, ip_addr, &host, responses, nb_threads); init_threads_data(options, ip_addr, &host, responses, nb_threads);
if (!threads_data) if (!threads_data)