diff --git a/include/host.h b/include/host.h new file mode 100644 index 0000000..ca37434 --- /dev/null +++ b/include/host.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include + +struct host { + char name[HOST_NAME_MAX]; + char ip[INET_ADDRSTRLEN]; + char interface[IFNAMSIZ]; +}; diff --git a/include/interface.h b/include/interface.h index 151765e..76a4720 100644 --- a/include/interface.h +++ b/include/interface.h @@ -1,3 +1,5 @@ #pragma once -char *get_interface_name(void); +#include "host.h" + +int get_interface_name(struct host *host); diff --git a/include/response.h b/include/response.h new file mode 100644 index 0000000..5d2ec7c --- /dev/null +++ b/include/response.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +#include "scan.h" + +typedef enum { + OPEN, + CLOSE, + FILTERED, + UNFILTERED, +} e_state; + +struct response { + uint16_t port; + e_state state; + char *service; +}; + +void tcp_response(struct tcphdr *tcp, const struct scan *data); +void udp_response(struct udphdr *udp, const struct scan *data); diff --git a/include/scan.h b/include/scan.h index b09d7b8..e0beeaf 100644 --- a/include/scan.h +++ b/include/scan.h @@ -2,6 +2,9 @@ #include +#include "host.h" +#include "response.h" + typedef enum { SCAN_SYN, SCAN_NULL, @@ -12,5 +15,13 @@ typedef enum { SCAN_TCP, } e_scantype; -int routine(const char *ip_addr, e_scantype type, uint16_t min_port, - uint16_t max_port); +struct scan { + const struct host *host; + const char *dest_addr; + uint16_t port_start; + uint16_t port; + e_scantype type; + struct response *response; +}; + +int scan(const struct scan *data); diff --git a/include/thread.h b/include/thread.h new file mode 100644 index 0000000..ee792a0 --- /dev/null +++ b/include/thread.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "host.h" +#include "response.h" +#include "scan.h" + +struct thread { + uint16_t port_start; + uint16_t port_end; + char *dest_addr; + e_scantype type; + struct host host; + struct response *responses; +}; + +void *routine(void *p_data); diff --git a/src/get_interface.c b/src/get_interface.c index 75b4e34..048ad80 100644 --- a/src/get_interface.c +++ b/src/get_interface.c @@ -1,24 +1,29 @@ #include #include -char *get_interface_name(void) +#include "host.h" + +int get_interface_name(struct host *host) { pcap_if_t *alldevs; char errbuf[PCAP_ERRBUF_SIZE]; if (pcap_findalldevs(&alldevs, errbuf) == -1) { dprintf(2, "Error finding devices: %s\n", errbuf); - return NULL; + return -1; } for (pcap_if_t *it = alldevs; it != NULL; it = it->next) { if (!(it->flags & PCAP_IF_LOOPBACK)) { - char *name = strdup(it->name); + struct sockaddr_in *tmp = + (struct sockaddr_in *)it->addresses->addr; + strcpy(host->interface, it->name); + strcpy(host->ip, inet_ntoa(tmp->sin_addr)); pcap_freealldevs(alldevs); - return name; + return 0; } } dprintf(2, "No non-loopback interface found.\n"); - return NULL; + return -1; } diff --git a/src/main.c b/src/main.c index 5c01a71..db71588 100644 --- a/src/main.c +++ b/src/main.c @@ -5,8 +5,10 @@ #include #include "dns.h" +#include "interface.h" #include "print.h" #include "scan.h" +#include "thread.h" int main(int ac, char **av) { @@ -26,7 +28,16 @@ int main(int ac, char **av) av[1]); return 1; } - if (routine(ip_addr, SCAN_SYN, 1, 1024) < 0) { + + struct response responses[1024]; + + struct thread *single_thread = malloc(sizeof(struct thread)); + if (get_interface_name(&single_thread->host) < 0) + return 1; + single_thread->port_start = 1; + single_thread->port_end = 1024; + single_thread->responses = responses; + if (routine(single_thread) == NULL) { dprintf(2, "ft_nmap: failed to scan ports\n"); return 1; } diff --git a/src/response.c b/src/response.c new file mode 100644 index 0000000..601e519 --- /dev/null +++ b/src/response.c @@ -0,0 +1,29 @@ +#include +#include +#include + +#include "response.h" +#include "scan.h" + +void hdr_response(struct tcphdr *hdr, const struct scan *data) +{ + if (data->type == SCAN_SYN) { + if (hdr->ack == 1 && hdr->syn == 1) + data->response->state = OPEN; + else if (hdr->ack == 1 && hdr->rst == 1) + data->response->state = CLOSE; + } else if (data->type == SCAN_ACK && hdr->rst == 1) + data->response->state = UNFILTERED; + else if (data->type == SCAN_NULL && hdr->rst == 1) + data->response->state = CLOSE; + else if (data->type == SCAN_FIN && hdr->rst == 1) + data->response->state = CLOSE; + else if (data->type == SCAN_XMAS && hdr->rst == 1) + data->response->state = CLOSE; +} + +void udp_response(struct udphdr *hdr, const struct scan *data) +{ + (void)hdr; + data->response->state = OPEN; +} diff --git a/src/scan.c b/src/scan.c index e0a2108..63a3da0 100644 --- a/src/scan.c +++ b/src/scan.c @@ -1,25 +1,89 @@ -#include +#include +#include +#include +#include +#include #include #include +#include -#include "error.h" -#include "interface.h" #include "scan.h" +#include "thread.h" -int routine(const char *ip_addr, e_scantype type, uint16_t min_port, - uint16_t max_port) +static void dispatch_callback(u_char *user, const struct pcap_pkthdr *h, + const u_char *bytes) { - int sockfd = - socket(AF_INET, type == SCAN_UDP ? SOCK_DGRAM : SOCK_STREAM, 0); - if (sockfd < 0) - return err("Failed to create socket"); + const struct scan *data = (struct scan *)user; + const struct iphdr *iphdr = + (struct iphdr *)(bytes + sizeof(struct ether_header)); - char *default_if = get_interface_name(); - printf("%s\n", default_if); + if ((data->type == SCAN_UDP && iphdr->protocol != IPPROTO_UDP) || + (data->type != SCAN_UDP && iphdr->protocol != IPPROTO_TCP)) { + dprintf(2, "ft_nmap: received packet from a different protocol " + "request\n"); + return; + } - (void)ip_addr; - for (int port = min_port; port <= max_port; port++) { - // scan(ip_addr, type, port); + if (iphdr->protocol == IPPROTO_TCP && + h->caplen >= sizeof(struct ether_header) + sizeof(struct iphdr) + + sizeof(struct tcphdr)) { + ; + } + if (iphdr->protocol == IPPROTO_UDP && + h->caplen >= sizeof(struct ether_header) + sizeof(struct iphdr) + + sizeof(struct udphdr)) { + ; + } +} + +int scan(const struct scan *data) +{ + int sockfd = socket( + AF_INET, data->type == SCAN_UDP ? SOCK_DGRAM : SOCK_STREAM, 0); + if (sockfd < 0) { + dprintf(2, "ft_nmap: failed to create socket"); + return -1; + } + + char errbuf[PCAP_ERRBUF_SIZE]; + bpf_u_int32 net, mask; + + if (pcap_lookupnet(data->host->interface, &net, &mask, errbuf) < 0) { + dprintf(2, "ft_nmap: failed to lookup net/mask\n"); + return -1; + } + + pcap_t *handle = + pcap_open_live(data->host->interface, BUFSIZ, 0, 1000, errbuf); + if (handle == NULL) { + dprintf(2, "ft_nmap: failed to open device capture\n"); + return -1; + } + + struct bpf_program fp; + char pcap_expr[BUFSIZ]; + sprintf(pcap_expr, "src host %s and src port %d and dst host %s", + data->dest_addr, data->port, data->host->ip); + + if (pcap_compile(handle, &fp, pcap_expr, 0, mask) < 0) { + dprintf(2, "ft_nmap: failed to lookup net/mask\n"); + pcap_close(handle); + return -1; + } + + if (pcap_setfilter(handle, &fp) < 0) { + dprintf(2, "ft_nmap: failed to set the filter\n"); + pcap_close(handle); + return -1; + } + + pcap_freecode(&fp); + + // send packets + + // TODO test with another cnt value + if (pcap_dispatch(handle, 10, dispatch_callback, (u_char *)data)) { + ; } return 0; diff --git a/src/thread.c b/src/thread.c new file mode 100644 index 0000000..cea0414 --- /dev/null +++ b/src/thread.c @@ -0,0 +1,27 @@ +#include +#include +#include + +#include "scan.h" +#include "thread.h" + +void *routine(void *p_data) +{ + 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, + }; + + for (uint16_t port = thread_data->port_start; + port <= thread_data->port_end; port++) { + scan_data.port = port; + scan_data.response = + &thread_data->responses[thread_data->port_start - port]; + scan(&scan_data); + } + + return p_data; +}