feature: start to implement responses
This commit is contained in:
parent
1361cd9f9c
commit
84d5960900
11
include/host.h
Normal file
11
include/host.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits.h>
|
||||
#include <linux/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct host {
|
||||
char name[HOST_NAME_MAX];
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
char interface[IFNAMSIZ];
|
||||
};
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
char *get_interface_name(void);
|
||||
#include "host.h"
|
||||
|
||||
int get_interface_name(struct host *host);
|
||||
|
23
include/response.h
Normal file
23
include/response.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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);
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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);
|
||||
|
18
include/thread.h
Normal file
18
include/thread.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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);
|
@ -1,24 +1,29 @@
|
||||
#include <pcap.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
13
src/main.c
13
src/main.c
@ -5,8 +5,10 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
29
src/response.c
Normal file
29
src/response.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
92
src/scan.c
92
src/scan.c
@ -1,25 +1,89 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <pcap.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#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;
|
||||
|
27
src/thread.c
Normal file
27
src/thread.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user