fix: pcap_dispatch is non blocking

feature: no response handle
This commit is contained in:
0x35c 2025-05-30 16:12:51 +02:00
parent 936c277d02
commit f35cad887d
6 changed files with 74 additions and 22 deletions

View File

@ -7,14 +7,20 @@
#include "scan.h"
#define TIMEOUT 1
typedef enum {
OPEN = 1,
CLOSE,
OPENED,
CLOSED,
FILTERED,
UNFILTERED,
OPENFILTERED,
} e_state;
[[__maybe_unused__]] static const char *states_str[] = {
"OPENED", "CLOSED", "FILTERED", "UNFILTERED", "OPENFILTERED",
};
struct response {
uint16_t port;
e_state states[SCAN_ALL];
@ -24,3 +30,4 @@ struct response {
void tcp_response(const struct tcphdr *tcphdr, const struct scan *data);
void udp_response(const struct udphdr *udphdr, const struct scan *data);
void icmp_response(const struct icmphdr *icmphdr, const struct scan *data);
void no_response(const struct scan *data);

View File

@ -28,6 +28,17 @@ static int scan_host(char *host, const struct option_lst *options)
struct response responses[1024] = {0};
if (create_threads(options, ip_addr, responses) < 0)
return 1;
static const char *types_str[] = {
"NULL", "SYN", "ACK", "FIN", "XMAS", "UDP",
};
for (uint16_t i = 0; i < 50; i++) {
printf("%d: ", i + 1);
for (e_scantype type = SCAN_NULL; type < SCAN_ALL; type++) {
printf("%s(%s) ", types_str[type],
states_str[responses[i].states[type]]);
}
printf("\n");
}
return 0;
}

View File

@ -31,7 +31,7 @@ char *get_option_arg(const struct option_lst *options, e_flag flag)
e_scantype parse_type(const char *arg)
{
const char *types[] = {
"SYN", "NULL", "ACK", "FIN", "XMAS", "UDP",
"NULL", "SYN", "ACK", "FIN", "XMAS", "UDP",
};
if (!arg)
@ -53,15 +53,17 @@ int parse_ports(const char *arg, uint16_t *p_start, uint16_t *p_end)
for (; isdigit(arg[i]); i++)
;
int start = atoi(arg);
if (arg[i] == '\0')
return 0;
if (arg[i++] != '-')
return -1;
goto error;
int end = atoi(arg + i);
for (; isdigit(arg[i]); i++)
;
if (arg[i])
return -1;
goto error;
if (start >= end)
return -1;
goto error;
if (end > UINT16_MAX) {
dprintf(2,
"ft_nmap: invalid argument: '%s': out of range: 0 "
@ -72,6 +74,9 @@ int parse_ports(const char *arg, uint16_t *p_start, uint16_t *p_end)
*p_start = start;
*p_end = end;
return 0;
error:
dprintf(2, "ft_nmap: invalid argument: '%s'\n", arg);
return -1;
}
static int check_arg(e_flag flag, const char *arg)

View File

@ -15,17 +15,17 @@ void tcp_response(const struct tcphdr *tcphdr, const struct scan *data)
}
if (type == SCAN_SYN) {
if (tcphdr->ack == 1 && tcphdr->syn == 1)
data->response->states[type] = OPEN;
data->response->states[type] = OPENED;
else if (tcphdr->ack == 1 && tcphdr->rst == 1)
data->response->states[type] = CLOSE;
data->response->states[type] = CLOSED;
} else if (type == SCAN_ACK && tcphdr->rst == 1)
data->response->states[type] = UNFILTERED;
else if (type == SCAN_NULL && tcphdr->rst == 1)
data->response->states[type] = CLOSE;
data->response->states[type] = CLOSED;
else if (type == SCAN_FIN && tcphdr->rst == 1)
data->response->states[type] = CLOSE;
data->response->states[type] = CLOSED;
else if (type == SCAN_XMAS && tcphdr->rst == 1)
data->response->states[type] = CLOSE;
data->response->states[type] = CLOSED;
}
void udp_response(const struct udphdr *udphdr, const struct scan *data)
@ -36,7 +36,7 @@ void udp_response(const struct udphdr *udphdr, const struct scan *data)
"scan\n");
return;
}
data->response->states[SCAN_UDP] = OPEN;
data->response->states[SCAN_UDP] = OPENED;
}
void icmp_response(const struct icmphdr *icmphdr, const struct scan *data)
@ -54,7 +54,25 @@ void icmp_response(const struct icmphdr *icmphdr, const struct scan *data)
else if (type == SCAN_XMAS && icmphdr->type == 3)
data->response->states[type] = FILTERED;
else if (type == SCAN_UDP && icmphdr->type == 3 && icmphdr->code == 3)
data->response->states[type] = CLOSE;
data->response->states[type] = CLOSED;
else if (type == SCAN_UDP && icmphdr->type == 3 && icmphdr->code != 3)
data->response->states[type] = FILTERED;
}
void no_response(const struct scan *data)
{
const e_scantype type = data->type;
if (type == SCAN_SYN)
data->response->states[type] = FILTERED;
else if (type == SCAN_ACK)
data->response->states[type] = FILTERED;
else if (type == SCAN_NULL)
data->response->states[type] = OPENFILTERED;
else if (type == SCAN_FIN)
data->response->states[type] = OPENFILTERED;
else if (type == SCAN_XMAS)
data->response->states[type] = OPENFILTERED;
else if (type == SCAN_UDP)
data->response->states[type] = OPENFILTERED;
}

View File

@ -39,6 +39,21 @@ static void dispatch_callback(u_char *user, const struct pcap_pkthdr *h,
}
}
static void send_recv_packet(const struct scan *data, int sockfd,
pcap_t *handle)
{
send_packet(data, sockfd);
uint8_t timer = 0;
for (; timer < TIMEOUT * 100; timer++) {
if (pcap_dispatch(handle, 1, dispatch_callback, (u_char *)data))
break;
usleep(100000);
}
if (timer == TIMEOUT * 100)
no_response(data);
pcap_breakloop(handle);
}
int scan(struct scan *data)
{
int sockfd = socket(AF_INET, SOCK_RAW,
@ -82,20 +97,16 @@ int scan(struct scan *data)
pcap_freecode(&fp);
pcap_setnonblock(handle, 1, errbuf);
if (data->type == SCAN_ALL) {
for (e_scantype type = SCAN_NULL; type < SCAN_ALL; type++) {
data->type = type;
send_packet(data, sockfd);
if (!pcap_dispatch(handle, 1, dispatch_callback,
(u_char *)data))
printf("timeout\n"); // TODO handle no response
send_recv_packet(data, sockfd, handle);
}
data->type = SCAN_ALL;
} else {
send_packet(data, sockfd);
if (!pcap_dispatch(handle, 1, dispatch_callback,
(u_char *)data))
printf("timeout\n");
send_recv_packet(data, sockfd, handle);
}
pcap_close(handle);

View File

@ -80,7 +80,7 @@ error:
int create_threads(const struct option_lst *options, char *ip_addr,
struct response *responses)
{
uint16_t port_start, port_end;
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;