From f35cad887d25d0fd603e75787ac79404809ebf12 Mon Sep 17 00:00:00 2001 From: 0x35c <> Date: Fri, 30 May 2025 16:12:51 +0200 Subject: [PATCH] fix: pcap_dispatch is non blocking feature: no response handle --- include/response.h | 11 +++++++++-- src/main.c | 11 +++++++++++ src/parsing.c | 13 +++++++++---- src/response.c | 32 +++++++++++++++++++++++++------- src/scan.c | 27 +++++++++++++++++++-------- src/thread.c | 2 +- 6 files changed, 74 insertions(+), 22 deletions(-) diff --git a/include/response.h b/include/response.h index cb1dd7c..af8ebcf 100644 --- a/include/response.h +++ b/include/response.h @@ -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); diff --git a/src/main.c b/src/main.c index 1e645a4..94ef69e 100644 --- a/src/main.c +++ b/src/main.c @@ -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; } diff --git a/src/parsing.c b/src/parsing.c index 5e431e6..bc672e5 100644 --- a/src/parsing.c +++ b/src/parsing.c @@ -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) diff --git a/src/response.c b/src/response.c index f6baefd..9f09b94 100644 --- a/src/response.c +++ b/src/response.c @@ -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; +} diff --git a/src/scan.c b/src/scan.c index ae65951..35f13c6 100644 --- a/src/scan.c +++ b/src/scan.c @@ -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); diff --git a/src/thread.c b/src/thread.c index 66b57a0..12940df 100644 --- a/src/thread.c +++ b/src/thread.c @@ -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;