diff --git a/include/parsing.h b/include/parsing.h index 21d3d8e..df966ac 100644 --- a/include/parsing.h +++ b/include/parsing.h @@ -28,6 +28,6 @@ struct option_lst { struct option_lst *parse_options(int ac, char *const *av); char *get_option_arg(const struct option_lst *options, e_flag flag); bool option_isset(const struct option_lst *options, e_flag flag); -e_scantype parse_type(const char *arg); +uint8_t parse_type(char *arg); void free_options(struct option_lst *options); int parsing(struct scan *general, const struct option_lst *options); diff --git a/include/response.h b/include/response.h index 3d611a9..1bbd3af 100644 --- a/include/response.h +++ b/include/response.h @@ -22,7 +22,7 @@ typedef enum { }; struct response { - e_state states[SCAN_ALL]; + e_state states[NB_SCAN]; char *service; }; diff --git a/include/scan.h b/include/scan.h index 38ba961..e13990c 100644 --- a/include/scan.h +++ b/include/scan.h @@ -4,26 +4,26 @@ #include "host.h" -typedef enum { - SCAN_NULL, - SCAN_SYN, - SCAN_ACK, - SCAN_FIN, - SCAN_XMAS, - SCAN_UDP, - SCAN_ALL, -} e_scantype; +#define SCAN_NULL (1 << 0) +#define SCAN_SYN (1 << 1) +#define SCAN_ACK (1 << 2) +#define SCAN_FIN (1 << 3) +#define SCAN_XMAS (1 << 4) +#define SCAN_UDP (1 << 5) +#define SCAN_ALL (SCAN_NULL | SCAN_SYN | SCAN_ACK | SCAN_FIN | SCAN_XMAS | SCAN_UDP) [[__maybe_unused__]] static const char *types_str[] = { "NULL", "SYN", "ACK", "FIN", "XMAS", "UDP", }; +#define NB_SCAN (sizeof(types_str) / sizeof(*types_str)) + struct scan { struct host host; char *dest_addr; uint16_t port_start; uint16_t port_end; - e_scantype type; + uint8_t type; uint8_t ttl; uint8_t max_retries; struct response *responses; diff --git a/src/packet.c b/src/packet.c index d96baba..6dcbf04 100644 --- a/src/packet.c +++ b/src/packet.c @@ -23,11 +23,11 @@ int create_tcp_packet(struct tcphdr *tcphdr, const struct scan *data) tcphdr->source = htons(1234); tcphdr->dest = htons(data->port_start); tcphdr->doff = sizeof(struct tcphdr) / sizeof(int); - tcphdr->fin = data->type == SCAN_XMAS || data->type == SCAN_FIN; - tcphdr->syn = data->type == SCAN_SYN; - tcphdr->psh = data->type == SCAN_XMAS; - tcphdr->ack = data->type == SCAN_ACK; - tcphdr->urg = data->type == SCAN_XMAS; + tcphdr->fin = ((data->type & SCAN_XMAS) != 0) || ((data->type & SCAN_FIN) != 0); + tcphdr->syn = ((data->type & SCAN_SYN) != 0); + tcphdr->psh = ((data->type & SCAN_XMAS) != 0); + tcphdr->ack = ((data->type & SCAN_ACK) != 0); + tcphdr->urg = ((data->type & SCAN_XMAS) != 0); tcphdr->window = htons(5840); tcphdr->urg_ptr = 0; @@ -52,7 +52,7 @@ int create_tcp_packet(struct tcphdr *tcphdr, const struct scan *data) static void *create_packet(const struct scan *data, size_t packet_size) { - const bool isudp = data->type == SCAN_UDP; + const bool isudp = ((data->type & SCAN_UDP) != 0); void *packet = calloc(packet_size, 1); if (!packet) { dprintf(2, @@ -90,7 +90,7 @@ int send_packet(const struct scan *data, int sockfd) conn_addr.sin_addr.s_addr = inet_addr(data->dest_addr); size_t packet_size = sizeof(struct iphdr) + - (data->type == SCAN_UDP ? sizeof(struct udphdr) + (((data->type & SCAN_UDP) != 0) ? sizeof(struct udphdr) : sizeof(struct tcphdr)); void *packet = create_packet(data, packet_size); diff --git a/src/parsing.c b/src/parsing.c index 2fca4f6..8a4d197 100644 --- a/src/parsing.c +++ b/src/parsing.c @@ -40,15 +40,36 @@ char *get_option_arg(const struct option_lst *options, e_flag flag) return NULL; } -e_scantype parse_type(const char *arg) +uint8_t parse_type(char *arg) { if (!arg) return SCAN_ALL; - for (size_t i = 0; i < 6; i++) - if (!strcmp(arg, types_str[i])) - return i; - dprintf(2, "ft_nmap: invalid argument to --scan: '%s'\n", arg); - return -1; + uint8_t type = 0; + char *current_arg = arg; + while (current_arg[0] != '\0') + { + if (strncmp(current_arg, "NULL", 4) == 0) + type |= SCAN_NULL; + else if (strncmp(current_arg, "SYN", 3) == 0) + type |= SCAN_SYN; + else if (strncmp(current_arg, "ACK", 3) == 0) + type |= SCAN_ACK; + else if (strncmp(current_arg, "FIN", 3) == 0) + type |= SCAN_FIN; + else if (strncmp(current_arg, "XMAS", 4) == 0) + type |= SCAN_XMAS; + else if (strncmp(current_arg, "UDP", 5) == 0) + type |= SCAN_UDP; + else + { + dprintf(2, "ft_nmap: invalid argument to --scan: '%s'\n", arg); + return -1; + } + current_arg += strcspn(current_arg, ","); + if (current_arg[0] == ',') + current_arg++; + } + return type; } int parse_ports(const char *arg, uint16_t *p_start, uint16_t *p_end) @@ -114,20 +135,6 @@ static int check_arg(e_flag flag, const char *arg) } break; } - case FL_TYPE: - 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; case FL_TTL: { int nb = atoi(arg); if (nb == 0) { @@ -248,7 +255,7 @@ int parsing(struct scan *general, const struct option_lst *options) return -1; } general->type = parse_type(get_option_arg(options, FL_TYPE)); - if ((int)general->type == -1) + if (general->type == (uint8_t) -1) return -1; const char *max_retries = get_option_arg(options, FL_MAXRETRIES); general->max_retries = max_retries ? atoi(max_retries) : 1; diff --git a/src/print.c b/src/print.c index 83c63b4..0eca1fb 100644 --- a/src/print.c +++ b/src/print.c @@ -31,20 +31,18 @@ void print_config(const struct scan *general, const char *hosts_path, printf("Number of scans to be performed: %d\n", general->port_end - general->port_start + 1); printf("Scans to be performed: "); - if (general->type == SCAN_ALL) - for (e_scantype type = SCAN_NULL; type < SCAN_ALL; type++) + for (uint8_t type = 0; type < NB_SCAN; type++) + if (general->type & (1 << type)) printf("%s ", types_str[type]); - else - printf("%s", types_str[general->type]); printf("\n"); if (nb_threads > 1) printf("No of threads: %d\n", nb_threads); } -bool is_port_opened(const e_state states[6], e_scantype type) +bool is_port_opened(const e_state states[6], uint8_t type) { if (type == SCAN_ALL) { - for (e_scantype i = SCAN_NULL; i < SCAN_ALL; i++) + for (uint8_t i = 0; i < NB_SCAN; i++) if (states[i] == OPENED) return true; return false; @@ -52,20 +50,19 @@ bool is_port_opened(const e_state states[6], e_scantype type) return states[type] == OPENED; } -static void print_port_state(uint16_t port, e_scantype type, +static void print_port_state(uint16_t port, uint8_t type, const struct response *response) { printf("%-5d %-12s ", port, response->service ? response->service : "Unassigned"); if (response->service) free(response->service); - if (type == SCAN_ALL) - for (e_scantype i = SCAN_NULL; i < SCAN_ALL; i++) + for (uint8_t i = 0; i < NB_SCAN; i++) + { + if ((1 << i) & type) printf("%s(%s) ", types_str[i], - states_str[response->states[i]]); - else - printf("%s(%s) ", types_str[type], - states_str[response->states[type]]); + states_str[response->states[i]]); + } printf("\n"); } diff --git a/src/response.c b/src/response.c index 672b28a..2acee4e 100644 --- a/src/response.c +++ b/src/response.c @@ -23,29 +23,39 @@ static char *get_service_name(int port, char *proto) void tcp_response(const struct tcphdr *tcphdr, const struct scan *data) { - const e_scantype type = data->type; - if (type == SCAN_UDP) { + if (data->type & SCAN_UDP) { dprintf(2, "ft_nmap: error: received a TCP responses for an UDP " "scan\n"); return; } + + uint8_t type_index; + for (uint8_t i = 0; i < NB_SCAN; i++) + { + if (data->type & (1 << i)) + { + type_index = i; + break; + } + } + if (data->responses->service == NULL) data->responses->service = get_service_name(data->port_start, "tcp"); - if (type == SCAN_SYN) { + if (data->type & SCAN_SYN) { if (tcphdr->ack == 1 && tcphdr->syn == 1) - data->responses->states[type] = OPENED; + data->responses->states[type_index] = OPENED; else if (tcphdr->ack == 1 && tcphdr->rst == 1) - data->responses->states[type] = CLOSED; - } else if (type == SCAN_ACK && tcphdr->rst == 1) - data->responses->states[type] = UNFILTERED; - else if (type == SCAN_NULL && tcphdr->rst == 1) - data->responses->states[type] = CLOSED; - else if (type == SCAN_FIN && tcphdr->rst == 1) - data->responses->states[type] = CLOSED; - else if (type == SCAN_XMAS && tcphdr->rst == 1) - data->responses->states[type] = CLOSED; + data->responses->states[type_index] = CLOSED; + } else if (data->type & SCAN_ACK && tcphdr->rst == 1) + data->responses->states[type_index] = UNFILTERED; + else if (data->type & SCAN_NULL && tcphdr->rst == 1) + data->responses->states[type_index] = CLOSED; + else if (data->type & SCAN_FIN && tcphdr->rst == 1) + data->responses->states[type_index] = CLOSED; + else if (data->type & SCAN_XMAS && tcphdr->rst == 1) + data->responses->states[type_index] = CLOSED; } void udp_response(const struct udphdr *udphdr, const struct scan *data) @@ -65,46 +75,62 @@ void udp_response(const struct udphdr *udphdr, const struct scan *data) void icmp_response(const struct icmphdr *icmphdr, const struct scan *data) { - const e_scantype type = data->type; + uint8_t type_index; + for (uint8_t i = 0; i < NB_SCAN; i++) + { + if (data->type & (1 << i)) + { + type_index = i; + break; + } + } data->responses->service = get_service_name(data->port_start, "udp"); if (data->responses->service == NULL) data->responses->service = get_service_name(data->port_start, "tcp"); - if (type == SCAN_SYN && icmphdr->type == 3) - data->responses->states[type] = FILTERED; - else if (type == SCAN_ACK && icmphdr->type == 3) - data->responses->states[type] = FILTERED; - else if (type == SCAN_NULL && icmphdr->type == 3) - data->responses->states[type] = FILTERED; - else if (type == SCAN_FIN && icmphdr->type == 3) - data->responses->states[type] = FILTERED; - else if (type == SCAN_XMAS && icmphdr->type == 3) - data->responses->states[type] = FILTERED; - else if (type == SCAN_UDP && icmphdr->type == 3 && icmphdr->code == 3) - data->responses->states[type] = CLOSED; - else if (type == SCAN_UDP && icmphdr->type == 3 && icmphdr->code != 3) - data->responses->states[type] = FILTERED; + if (data->type & SCAN_SYN && icmphdr->type == 3) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_ACK && icmphdr->type == 3) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_NULL && icmphdr->type == 3) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_FIN && icmphdr->type == 3) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_XMAS && icmphdr->type == 3) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_UDP && icmphdr->type == 3 && icmphdr->code == 3) + data->responses->states[type_index] = CLOSED; + else if (data->type & SCAN_UDP && icmphdr->type == 3 && icmphdr->code != 3) + data->responses->states[type_index] = FILTERED; } void no_response(const struct scan *data) { - const e_scantype type = data->type; + uint8_t type_index; + for (uint8_t i = 0; i < NB_SCAN; i++) + { + if (data->type & (1 << i)) + { + type_index = i; + break; + } + } data->responses->service = get_service_name(data->port_start, "udp"); if (data->responses->service == NULL) data->responses->service = get_service_name(data->port_start, "tcp"); - if (type == SCAN_SYN) - data->responses->states[type] = FILTERED; - else if (type == SCAN_ACK) - data->responses->states[type] = FILTERED; - else if (type == SCAN_NULL) - data->responses->states[type] = OPENFILTERED; - else if (type == SCAN_FIN) - data->responses->states[type] = OPENFILTERED; - else if (type == SCAN_XMAS) - data->responses->states[type] = OPENFILTERED; - else if (type == SCAN_UDP) - data->responses->states[type] = OPENFILTERED; + if (data->type & SCAN_SYN) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_ACK) + data->responses->states[type_index] = FILTERED; + else if (data->type & SCAN_NULL) + data->responses->states[type_index] = OPENFILTERED; + else if (data->type & SCAN_FIN) + data->responses->states[type_index] = OPENFILTERED; + else if (data->type & SCAN_XMAS) + data->responses->states[type_index] = OPENFILTERED; + else if (data->type & SCAN_UDP) + data->responses->states[type_index] = OPENFILTERED; } diff --git a/src/scan.c b/src/scan.c index 3e54654..27b099d 100644 --- a/src/scan.c +++ b/src/scan.c @@ -107,20 +107,19 @@ int scan(struct scan *data) pcap_setnonblock(handle, 1, errbuf); - if (data->type == SCAN_ALL) { - for (e_scantype type = SCAN_NULL; type < SCAN_ALL; type++) { - data->type = type; + for (uint8_t type = 0; type < NB_SCAN; type++) { + uint8_t type_bak = data->type; + data->type = data->type & (1 << type); + if (data->type) + { for (uint8_t retries = 0; retries < data->max_retries; - retries++) + retries++) + { if (send_recv_packet(data, sockfd, handle)) break; + } } - data->type = SCAN_ALL; - } else { - for (uint8_t retries = 0; retries < data->max_retries; - retries++) - if (send_recv_packet(data, sockfd, handle)) - break; + data->type = type_bak; } pcap_close(handle);