FreeBSD port initial checkin. This is based on 5cd6f3294c
,
September 9, 2013, before CMake changes. Includes proto_headers.h. Most or all of __FREEBSD__ changes should, IMHO, be merged back into Linux version. This should build on Linux with __FREEBSD__ defined.
This commit is contained in:
parent
5cd6f3294c
commit
833c781d94
59
src/Makefile
59
src/Makefile
@ -1,10 +1,25 @@
|
||||
INCLUDE+=-I../lib -I./ -Ioutput_modules
|
||||
LDFLAGS+=-pthread
|
||||
LDLIBS+=-lpcap -lgmp -lm
|
||||
#<<<<<<< HEAD
|
||||
CC=gcc
|
||||
#CC=clang
|
||||
|
||||
#CFLAGS=-Wall -pedantic -Wextra -std=gnu99 -I../lib -I./ -Ioutput_modules -O2 -g
|
||||
#wbk makefile hack to get rolling with C port. Fix later lol
|
||||
CFLAGS=-Wall -pedantic -Wextra -std=gnu99 -I../lib -I./ -Ioutput_modules \
|
||||
-O2 -g -D__FREEBSD__ -D__FREEBSD_INCLUDES__ -D__FREEBSD_PTHREADS__ -DZMAP_PCAP_INJECT
|
||||
LDFLAGS=-g -pthread
|
||||
LDLIBS= -lpcap -lgmp -lm
|
||||
#=======
|
||||
#INCLUDE+=-I../lib -I./ -Ioutput_modules
|
||||
#LDFLAGS+=-pthread
|
||||
#LDLIBS+=-lpcap -lgmp -lm
|
||||
#>>>>>>> 5cd6f3294cb4f6ddf711b4c42d72893989a9dc3d
|
||||
TARGETS=zmap
|
||||
VPATH=../lib:output_modules:probe_modules
|
||||
PREFIX=/usr/local
|
||||
|
||||
#wbk
|
||||
LIBDIR=/usr/local/lib
|
||||
|
||||
INSTALL=install
|
||||
INSTALLDATA=install -m 644
|
||||
mandir=$(PREFIX)/man/man1/
|
||||
@ -12,23 +27,43 @@ oldmanfile=/usr/share/man/man1/zmap.1
|
||||
bindir=$(PREFIX)/sbin
|
||||
|
||||
# Hardening and warnings for building with gcc
|
||||
#<<<<<<< HEAD
|
||||
#M aybe add -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
|
||||
GCCWARNINGS = -Wall -Wformat=2 -Wno-format-nonliteral\
|
||||
-pedantic -fno-strict-aliasing \
|
||||
-Wextra \
|
||||
-Wfloat-equal -Wundef -Wwrite-strings -Wredundant-decls \
|
||||
#-Wold-style-definition -Wswitch-enum
|
||||
GCCWARNINGS = -Wall -fno-strict-aliasing -W -Wfloat-equal -Wundef \
|
||||
-Wpointer-arith \
|
||||
-Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment \
|
||||
-Wformat=2 -Wwrite-strings -Wredundant-decls \
|
||||
-Wnested-externs -Wbad-function-cast -Winit-self \
|
||||
-Wmissing-noreturn -Wnormalized=id \
|
||||
-Wstack-protector
|
||||
-Wmissing-field-initializers \
|
||||
-Waddress -Wmissing-noreturn -Wnormalized=id \
|
||||
-Woverride-init -Wstrict-overflow=1 -Wextra \
|
||||
-Wstack-protector -Wformat -Wformat-security -Wpointer-sign -Wno-format-nonliteral -Wno-format-y2k
|
||||
GCCHARDENING=-D_FORTIFY_SOURCE=2 -fstack-protector-all -fwrapv -fPIC --param ssp-buffer-size=1
|
||||
# clang doesn't like this
|
||||
#LDHARDENING=-z relro -z now
|
||||
|
||||
GCCHARDENING=-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all -fwrapv -fPIC --param ssp-buffer-size=1
|
||||
LDHARDENING=-z relro -z now
|
||||
EXTRACFLAGS=-g -O2 $(EXTRA_CFLAGS) $(GCCHARDENING) $(GCCWARNINGS)
|
||||
#=======
|
||||
# Maybe add -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
|
||||
#GCCWARNINGS = -Wall -Wformat=2 -Wno-format-nonliteral\
|
||||
#-pedantic -fno-strict-aliasing \
|
||||
#-Wextra \
|
||||
#-Wfloat-equal -Wundef -Wwrite-strings -Wredundant-decls \
|
||||
#-Wnested-externs -Wbad-function-cast -Winit-self \
|
||||
#-Wmissing-noreturn -Wnormalized=id \
|
||||
#-Wstack-protector
|
||||
|
||||
EXTRACFLAGS=-std=gnu99 -g -O2 $(GCCHARDENING) $(GCCWARNINGS) $(EXTRA_CFLAGS) -Werror
|
||||
#GCCHARDENING=-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all -fwrapv -fPIC --param ssp-buffer-size=1
|
||||
#LDHARDENING=-z relro -z now
|
||||
|
||||
#EXTRACFLAGS=-std=gnu99 -g -O2 $(GCCHARDENING) $(GCCWARNINGS) $(EXTRA_CFLAGS) -Werror
|
||||
#>>>>>>> 5cd6f3294cb4f6ddf711b4c42d72893989a9dc3d
|
||||
EXTRALDFLAGS= $(LDHARDENING)
|
||||
|
||||
CFLAGS+=$(INCLUDE) $(EXTRACFLAGS)
|
||||
LDFLAGS+=$(EXTRALDFLAGS)
|
||||
LDFLAGS+=-L$(LIBDIR)
|
||||
|
||||
probemodules=module_tcp_synscan.o module_icmp_echo.o module_udp.o #ADD YOUR PROBE MODULE HERE
|
||||
outputmodules= module_csv.o #ADD YOUR OUTPUT MODULE HERE
|
||||
|
@ -48,7 +48,11 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef __FREEBSD_INCLUDES__
|
||||
#include </usr/local/include/gmp.h>
|
||||
#else
|
||||
#include <gmp.h>
|
||||
#endif
|
||||
|
||||
#include "../lib/logger.h"
|
||||
#include "../lib/blacklist.h"
|
||||
|
@ -35,6 +35,8 @@ fieldset_t *fs_new_fieldset(void)
|
||||
return f;
|
||||
}
|
||||
|
||||
/* wbk TODO: Might have some subtle issues here on 32 bit architectures. Getting
|
||||
compiler warnings about casting void* to uint64_t */
|
||||
static inline void fs_add_word(fieldset_t *fs, const char *name, int type,
|
||||
int free_, size_t len, void *value)
|
||||
{
|
||||
|
@ -15,16 +15,22 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#ifdef __FREEBSD__
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "../lib/logger.h"
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
#else
|
||||
int read_nl_sock(int sock, char *buf, int buf_len)
|
||||
{
|
||||
int msg_len = 0;
|
||||
@ -87,7 +93,14 @@ int send_nl_req(uint16_t msg_type, uint32_t seq,
|
||||
free(nlmsg);
|
||||
return sock;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac) {
|
||||
log_fatal("get-gw", "get_hw_addr() not yet implemented for BSD");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac)
|
||||
{
|
||||
char buf[8192];
|
||||
@ -164,8 +177,19 @@ int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// gw and iface[IF_NAMESIZE] MUST be allocated
|
||||
/* wbk TODO: Need a better understanding of what the Linux rt stuff
|
||||
is doing. May be portable to BSD using different constants */
|
||||
#ifdef __FREEBSD__
|
||||
/* TODO */
|
||||
int get_default_gw(struct in_addr *gw, char *iface)
|
||||
{
|
||||
log_fatal("get-gw", "get_default_gw() not yet implemented for BSD; use -G [router MAC] instead");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int get_default_gw(struct in_addr *gw, char *iface)
|
||||
{
|
||||
struct rtmsg req;
|
||||
@ -223,8 +247,29 @@ int get_default_gw(struct in_addr *gw, char *iface)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns the first IP address for a given iface
|
||||
#ifdef __FREEBSD__
|
||||
int get_iface_ip(char *iface, struct in_addr *ip)
|
||||
{
|
||||
/* retrieve IP address using getifaddrs(). Should port across BSD's. */
|
||||
struct ifaddrs *p = NULL;
|
||||
struct sockaddr_in *sin = NULL;
|
||||
if (getifaddrs(&p) == -1) {
|
||||
log_fatal("get_getway", "get_if_ip() getifaddrs() failed!");
|
||||
}
|
||||
for (; p != NULL; p = p->ifa_next) {
|
||||
if ( (p->ifa_addr->sa_family == AF_INET)
|
||||
&& (strncmp(iface, p->ifa_name, IF_NAMESIZE) == 0) )
|
||||
{
|
||||
sin = (struct sockaddr_in *)(p->ifa_addr);
|
||||
memcpy(ip, &(sin->sin_addr), sizeof(*ip));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
int get_iface_ip(char *iface, struct in_addr *ip)
|
||||
{
|
||||
int sock;
|
||||
@ -246,4 +291,4 @@ int get_iface_ip(char *iface, struct in_addr *ip)
|
||||
memcpy(ip, &((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr, sizeof(*ip));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,12 +15,14 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __FREEBSD__
|
||||
#include <netinet/ether.h>
|
||||
#endif
|
||||
#include <netinet/in.h> /* wbk order */
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "probe_modules.h"
|
||||
@ -35,11 +37,20 @@ int icmp_echo_init_perthread(void* buf, macaddr_t *src,
|
||||
{
|
||||
memset(buf, 0, MAX_PACKET_SIZE);
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth_header = (struct zmap_ethhdr *)buf;
|
||||
#else
|
||||
struct ethhdr *eth_header = (struct ethhdr *)buf;
|
||||
#endif
|
||||
make_eth_header(eth_header, src, gw);
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_header = (struct zmap_iphdr*)(ð_header[1]);
|
||||
uint16_t len = htons(sizeof(struct zmap_iphdr) + sizeof(struct icmp) - 8);
|
||||
#else
|
||||
struct iphdr *ip_header = (struct iphdr*)(ð_header[1]);
|
||||
uint16_t len = htons(sizeof(struct iphdr) + sizeof(struct icmp) - 8);
|
||||
#endif
|
||||
make_ip_header(ip_header, IPPROTO_ICMP, len);
|
||||
|
||||
struct icmp *icmp_header = (struct icmp*)(&ip_header[1]);
|
||||
@ -51,13 +62,23 @@ int icmp_echo_init_perthread(void* buf, macaddr_t *src,
|
||||
int icmp_echo_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
|
||||
uint32_t *validation, __attribute__((unused))int probe_num)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth_header = (struct zmap_ethhdr *)buf;
|
||||
struct zmap_iphdr *ip_header = (struct zmap_iphdr*)(ð_header[1]);
|
||||
#else
|
||||
struct ethhdr *eth_header = (struct ethhdr *)buf;
|
||||
struct iphdr *ip_header = (struct iphdr*)(ð_header[1]);
|
||||
struct icmp *icmp_header = (struct icmp*)(&ip_header[1]);
|
||||
#endif
|
||||
struct icmp *icmp_header = (struct icmp*)(&ip_header[1]); /* TODO: struct icmp? */
|
||||
uint16_t icmp_idnum = validation[2] & 0xFFFF;
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
ip_header->saddr.s_addr = src_ip;
|
||||
ip_header->daddr.s_addr = dst_ip;
|
||||
#else
|
||||
ip_header->saddr = src_ip;
|
||||
ip_header->daddr = dst_ip;
|
||||
#endif
|
||||
|
||||
icmp_header->icmp_id = icmp_idnum;
|
||||
icmp_header->icmp_cksum = 0;
|
||||
@ -71,8 +92,13 @@ int icmp_echo_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
|
||||
|
||||
void icmp_echo_print_packet(FILE *fp, void* packet)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *ethh = (struct zmap_ethhdr *) packet;
|
||||
struct zmap_iphdr *iph = (struct zmap_iphdr *) ðh[1];
|
||||
#else
|
||||
struct ethhdr *ethh = (struct ethhdr *) packet;
|
||||
struct iphdr *iph = (struct iphdr *) ðh[1];
|
||||
#endif
|
||||
struct icmp *icmp_header = (struct icmp*)(&iph[1]);
|
||||
|
||||
fprintf(fp, "icmp { type: %u | code: %u "
|
||||
@ -87,10 +113,13 @@ void icmp_echo_print_packet(FILE *fp, void* packet)
|
||||
fprintf(fp, "------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
int icmp_validate_packet(const struct zmap_iphdr *ip_hdr,
|
||||
uint32_t len, uint32_t *src_ip, uint32_t *validation)
|
||||
#else
|
||||
int icmp_validate_packet(const struct iphdr *ip_hdr,
|
||||
uint32_t len, uint32_t *src_ip, uint32_t *validation)
|
||||
#endif
|
||||
{
|
||||
if (ip_hdr->protocol != IPPROTO_ICMP) {
|
||||
return 0;
|
||||
@ -101,27 +130,50 @@ int icmp_validate_packet(const struct iphdr *ip_hdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_icmphdr *icmp_h = (struct zmap_icmphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#else
|
||||
struct icmphdr *icmp_h = (struct icmphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#endif
|
||||
uint16_t icmp_idnum = icmp_h->un.echo.id;
|
||||
|
||||
// ICMP validation is tricky: for some packet types, we must look inside
|
||||
// the payload
|
||||
if (icmp_h->type == ICMP_TIME_EXCEEDED || icmp_h->type == ICMP_DEST_UNREACH) {
|
||||
if ((4*ip_hdr->ihl + sizeof(struct icmphdr) +
|
||||
#ifdef __FREEBSD__
|
||||
sizeof(struct zmap_iphdr)) > len) {
|
||||
#else
|
||||
sizeof(struct iphdr)) > len) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_inner = (struct zmap_iphdr *)(icmp_h + 1);
|
||||
if ((4*ip_hdr->ihl + sizeof(struct zmap_icmphdr) +
|
||||
4*ip_inner->ihl + sizeof(struct zmap_icmphdr)) > len) {
|
||||
#else
|
||||
struct iphdr *ip_inner = (struct iphdr *)(icmp_h + 1);
|
||||
if ((4*ip_hdr->ihl + sizeof(struct icmphdr) +
|
||||
4*ip_inner->ihl + sizeof(struct icmphdr)) > len) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_icmphdr *icmp_inner = (struct zmap_icmphdr*)((char *)ip_inner + 4 *ip_hdr->ihl);
|
||||
#else
|
||||
struct icmphdr *icmp_inner = (struct icmphdr*)((char *)ip_inner + 4 *ip_hdr->ihl);
|
||||
#endif
|
||||
|
||||
// Regenerate validation and icmp id based off inner payload
|
||||
icmp_idnum = icmp_inner->un.echo.id;
|
||||
#ifdef __FREEBSD__
|
||||
*src_ip = ip_inner->daddr.s_addr;
|
||||
validate_gen(ip_hdr->daddr.s_addr, ip_inner->daddr.s_addr, (uint8_t *)validation);
|
||||
#else
|
||||
*src_ip = ip_inner->daddr;
|
||||
validate_gen(ip_hdr->daddr, ip_inner->daddr, (uint8_t *)validation);
|
||||
#endif
|
||||
}
|
||||
|
||||
// validate icmp id
|
||||
@ -135,8 +187,13 @@ int icmp_validate_packet(const struct iphdr *ip_hdr,
|
||||
void icmp_echo_process_packet(const u_char *packet,
|
||||
__attribute__((unused)) uint32_t len, fieldset_t *fs)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_hdr = (struct zmap_iphdr *)&packet[sizeof(struct zmap_ethhdr)];
|
||||
struct zmap_icmphdr *icmp_hdr = (struct zmap_icmphdr*)((char *)ip_hdr + 4 *ip_hdr->ihl);
|
||||
#else
|
||||
struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)];
|
||||
struct icmphdr *icmp_hdr = (struct icmphdr*)((char *)ip_hdr + 4 *ip_hdr->ihl);
|
||||
#endif
|
||||
fs_add_uint64(fs, "type", icmp_hdr->type);
|
||||
fs_add_uint64(fs, "code", icmp_hdr->code);
|
||||
fs_add_uint64(fs, "icmp-id", ntohs(icmp_hdr->un.echo.id));
|
||||
|
@ -15,9 +15,16 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __FREEBSD__ // TODO: __FREEBSD_INCLUDES__?
|
||||
/* TODO: This may break Linux, might need to remove #ifdef here entirely */
|
||||
#include <netinet/in.h> /* wbk needed before netinet/ip.h */
|
||||
#endif
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef __FREEBSD__
|
||||
#else
|
||||
#include <netinet/ether.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
@ -40,12 +47,25 @@ int synscan_init_perthread(void* buf, macaddr_t *src,
|
||||
macaddr_t *gw, port_h_t dst_port)
|
||||
{
|
||||
memset(buf, 0, MAX_PACKET_SIZE);
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth_header = (struct zmap_ethhdr *)buf;
|
||||
#else
|
||||
struct ethhdr *eth_header = (struct ethhdr *)buf;
|
||||
#endif
|
||||
make_eth_header(eth_header, src, gw);
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_header = (struct zmap_iphdr*)(ð_header[1]);
|
||||
uint16_t len = htons(sizeof(struct zmap_iphdr) + sizeof(struct zmap_tcphdr));
|
||||
#else
|
||||
struct iphdr *ip_header = (struct iphdr*)(ð_header[1]);
|
||||
uint16_t len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
|
||||
#endif
|
||||
make_ip_header(ip_header, IPPROTO_TCP, len);
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_tcphdr *tcp_header = (struct zmap_tcphdr*)(&ip_header[1]);
|
||||
#else
|
||||
struct tcphdr *tcp_header = (struct tcphdr*)(&ip_header[1]);
|
||||
#endif
|
||||
make_tcp_header(tcp_header, dst_port);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -53,20 +73,45 @@ int synscan_init_perthread(void* buf, macaddr_t *src,
|
||||
int synscan_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
|
||||
uint32_t *validation, int probe_num)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth_header = (struct zmap_ethhdr *)buf;
|
||||
struct zmap_iphdr *ip_header = (struct zmap_iphdr*)(ð_header[1]);
|
||||
struct zmap_tcphdr *tcp_header = (struct zmap_tcphdr*)(&ip_header[1]); /* How does this work? What about options? */
|
||||
#else
|
||||
struct ethhdr *eth_header = (struct ethhdr *)buf;
|
||||
struct iphdr *ip_header = (struct iphdr*)(ð_header[1]);
|
||||
struct tcphdr *tcp_header = (struct tcphdr*)(&ip_header[1]);
|
||||
#endif
|
||||
uint32_t tcp_seq = validation[0];
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
ip_header->saddr.s_addr = src_ip;
|
||||
ip_header->daddr.s_addr = dst_ip;
|
||||
#else
|
||||
ip_header->saddr = src_ip;
|
||||
ip_header->daddr = dst_ip;
|
||||
#endif
|
||||
|
||||
tcp_header->source = htons(get_src_port(num_ports,
|
||||
probe_num, validation));
|
||||
tcp_header->seq = tcp_seq;
|
||||
tcp_header->check = 0;
|
||||
#ifdef __FREEBSD__
|
||||
tcp_header->check = tcp_checksum(sizeof(struct zmap_tcphdr),
|
||||
ip_header->saddr.s_addr, ip_header->daddr.s_addr, tcp_header);
|
||||
|
||||
/* wbk Set TCP data offset. I think Linux SOCK_RAW might have set this for us
|
||||
on Linux. Hardcoding for now. */
|
||||
//tcp_header->th_offx2 = 0x50;
|
||||
//tcp_header->th_flags = 0x02;
|
||||
/* If we ever add TCP options, we'll need to calculate header length in words and replace
|
||||
5 with that. */
|
||||
tcp_header->th_offx2 = (0x5 << 4);
|
||||
tcp_header->th_flags = TH_SYN;
|
||||
#else
|
||||
tcp_header->check = tcp_checksum(sizeof(struct tcphdr),
|
||||
ip_header->saddr, ip_header->daddr, tcp_header);
|
||||
#endif
|
||||
|
||||
ip_header->check = 0;
|
||||
ip_header->check = ip_checksum((unsigned short *) ip_header);
|
||||
@ -76,9 +121,15 @@ int synscan_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
|
||||
|
||||
void synscan_print_packet(FILE *fp, void* packet)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *ethh = (struct zmap_ethhdr *) packet;
|
||||
struct zmap_iphdr *iph = (struct zmap_iphdr *) ðh[1];
|
||||
struct zmap_tcphdr *tcph = (struct zmap_tcphdr *) &iph[1];
|
||||
#else
|
||||
struct ethhdr *ethh = (struct ethhdr *) packet;
|
||||
struct iphdr *iph = (struct iphdr *) ðh[1];
|
||||
struct tcphdr *tcph = (struct tcphdr *) &iph[1];
|
||||
#endif
|
||||
fprintf(fp, "tcp { source: %u | dest: %u | seq: %u | checksum: %u }\n",
|
||||
ntohs(tcph->source),
|
||||
ntohs(tcph->dest),
|
||||
@ -89,9 +140,15 @@ void synscan_print_packet(FILE *fp, void* packet)
|
||||
fprintf(fp, "------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
int synscan_validate_packet(const struct zmap_iphdr *ip_hdr, uint32_t len,
|
||||
__attribute__((unused))uint32_t *src_ip,
|
||||
uint32_t *validation)
|
||||
#else
|
||||
int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len,
|
||||
__attribute__((unused))uint32_t *src_ip,
|
||||
uint32_t *validation)
|
||||
#endif
|
||||
{
|
||||
if (ip_hdr->protocol != IPPROTO_TCP) {
|
||||
return 0;
|
||||
@ -100,7 +157,11 @@ int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len,
|
||||
// buffer not large enough to contain expected tcp header
|
||||
return 0;
|
||||
}
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_tcphdr *tcp = (struct zmap_tcphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);/*TODO*/
|
||||
#else
|
||||
struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#endif
|
||||
uint16_t sport = tcp->source;
|
||||
uint16_t dport = tcp->dest;
|
||||
// validate source port
|
||||
@ -121,17 +182,31 @@ int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len,
|
||||
void synscan_process_packet(const u_char *packet,
|
||||
__attribute__((unused)) uint32_t len, fieldset_t *fs)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_hdr = (struct zmap_iphdr *)&packet[sizeof(struct zmap_ethhdr)];
|
||||
struct zmap_tcphdr *tcp = (struct zmap_tcphdr*)((char *)ip_hdr
|
||||
+ (sizeof(struct zmap_iphdr)));
|
||||
#else
|
||||
struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)];
|
||||
struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr
|
||||
+ (sizeof(struct iphdr)));
|
||||
#endif
|
||||
|
||||
fs_add_uint64(fs, "sport", (uint64_t) ntohs(tcp->source));
|
||||
fs_add_uint64(fs, "dport", (uint64_t) ntohs(tcp->dest));
|
||||
fs_add_uint64(fs, "seqnum", (uint64_t) ntohl(tcp->seq));
|
||||
fs_add_uint64(fs, "acknum", (uint64_t) ntohl(tcp->ack_seq));
|
||||
#ifdef __FREEBSD__
|
||||
fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->th_win));
|
||||
#else
|
||||
fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->window));
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
if (tcp->th_flags & TH_RST) { // RST packet
|
||||
#else
|
||||
if (tcp->rst) { // RST packet
|
||||
#endif
|
||||
fs_add_string(fs, "classification", (char*) "rst", 0);
|
||||
fs_add_uint64(fs, "success", 0);
|
||||
} else { // SYNACK packet
|
||||
|
@ -16,12 +16,17 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/in.h> /* wbk order */
|
||||
#include <netinet/ip.h>
|
||||
#ifdef __FREEBSD__
|
||||
#include "proto_headers.h" /* wbk TODO: test */
|
||||
#else
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/ether.h> /* wbk TODO: Probably need proto_headers.h instead */
|
||||
#include <netinet/ip_icmp.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "probe_modules.h"
|
||||
@ -159,20 +164,36 @@ int udp_init_perthread(void* buf, macaddr_t *src,
|
||||
macaddr_t *gw, __attribute__((unused)) port_h_t dst_port)
|
||||
{
|
||||
memset(buf, 0, MAX_PACKET_SIZE);
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth_header = (struct zmap_ethhdr *)buf;
|
||||
make_eth_header(eth_header, src, gw);
|
||||
struct zmap_iphdr *ip_header = (struct zmap_iphdr*)(ð_header[1]);
|
||||
uint16_t len = htons(sizeof(struct zmap_iphdr) + sizeof(struct zmap_udphdr) + udp_send_msg_len);
|
||||
#else
|
||||
struct ethhdr *eth_header = (struct ethhdr *)buf;
|
||||
make_eth_header(eth_header, src, gw);
|
||||
struct iphdr *ip_header = (struct iphdr*)(ð_header[1]);
|
||||
uint16_t len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + udp_send_msg_len);
|
||||
#endif
|
||||
make_ip_header(ip_header, IPPROTO_UDP, len);
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_udphdr *udp_header = (struct zmap_udphdr*)(&ip_header[1]);
|
||||
#else
|
||||
struct udphdr *udp_header = (struct udphdr*)(&ip_header[1]);
|
||||
#endif
|
||||
len = sizeof(struct udphdr) + udp_send_msg_len;
|
||||
make_udp_header(udp_header, zconf.target_port, len);
|
||||
|
||||
char* payload = (char*)(&udp_header[1]);
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
module_udp.packet_length = sizeof(struct zmap_ethhdr) + sizeof(struct zmap_iphdr)
|
||||
+ sizeof(struct zmap_udphdr) + udp_send_msg_len;
|
||||
#else
|
||||
module_udp.packet_length = sizeof(struct ethhdr) + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + udp_send_msg_len;
|
||||
#endif
|
||||
assert(module_udp.packet_length <= MAX_PACKET_SIZE);
|
||||
|
||||
memcpy(payload, udp_send_msg, udp_send_msg_len);
|
||||
@ -183,12 +204,24 @@ int udp_init_perthread(void* buf, macaddr_t *src,
|
||||
int udp_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
|
||||
uint32_t *validation, int probe_num)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth_header = (struct zmap_ethhdr *)buf;
|
||||
struct zmap_iphdr *ip_header = (struct zmap_iphdr*)(ð_header[1]);
|
||||
struct zmap_udphdr *udp_header = (struct zmap_udphdr*)(&ip_header[1]);
|
||||
#else
|
||||
struct ethhdr *eth_header = (struct ethhdr *)buf;
|
||||
struct iphdr *ip_header = (struct iphdr*)(ð_header[1]);
|
||||
struct udphdr *udp_header = (struct udphdr*)(&ip_header[1]);
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
ip_header->saddr.s_addr = src_ip;
|
||||
ip_header->daddr.s_addr = dst_ip;
|
||||
#else
|
||||
ip_header->saddr = src_ip;
|
||||
ip_header->daddr = dst_ip;
|
||||
#endif
|
||||
|
||||
udp_header->source = get_src_port(num_ports, probe_num,
|
||||
validation);
|
||||
ip_header->check = 0;
|
||||
@ -199,9 +232,15 @@ int udp_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
|
||||
|
||||
void udp_print_packet(FILE *fp, void* packet)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *ethh = (struct zmap_ethhdr *) packet;
|
||||
struct zmap_iphdr *iph = (struct zmap_iphdr *) ðh[1];
|
||||
struct zmap_udphdr *udph = (struct zmap_udphdr*)(&iph[1]);
|
||||
#else
|
||||
struct ethhdr *ethh = (struct ethhdr *) packet;
|
||||
struct iphdr *iph = (struct iphdr *) ðh[1];
|
||||
struct udphdr *udph = (struct udphdr*)(&iph[1]);
|
||||
#endif
|
||||
fprintf(fp, "udp { source: %u | dest: %u | checksum: %u }\n",
|
||||
ntohs(udph->source),
|
||||
ntohs(udph->dest),
|
||||
@ -213,9 +252,16 @@ void udp_print_packet(FILE *fp, void* packet)
|
||||
|
||||
void udp_process_packet(const u_char *packet, UNUSED uint32_t len, fieldset_t *fs)
|
||||
{
|
||||
struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)];
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_hdr = (struct zmap_iphdr *)&packet[sizeof(struct zmap_ethhdr)];
|
||||
#else
|
||||
#endif
|
||||
if (ip_hdr->protocol == IPPROTO_UDP) {
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_udphdr *udp = (struct zmap_udphdr *)((char *)ip_hdr + ip_hdr->ihl * 4);
|
||||
#else
|
||||
struct udphdr *udp = (struct udphdr *)((char *)ip_hdr + ip_hdr->ihl * 4);
|
||||
#endif
|
||||
fs_add_string(fs, "classification", (char*) "udp", 0);
|
||||
fs_add_uint64(fs, "success", 1);
|
||||
fs_add_uint64(fs, "sport", ntohs(udp->source));
|
||||
@ -226,16 +272,21 @@ void udp_process_packet(const u_char *packet, UNUSED uint32_t len, fieldset_t *f
|
||||
fs_add_null(fs, "icmp_unreach_str");
|
||||
fs_add_binary(fs, "data", (ntohs(udp->len) - sizeof(struct udphdr)), (void*) &udp[1], 0);
|
||||
} else if (ip_hdr->protocol == IPPROTO_ICMP) {
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_icmphdr *icmp = (struct zmap_icmphdr *)((char *)ip_hdr + ip_hdr->ihl * 4);
|
||||
struct zmap_iphdr *ip_inner = (struct zmap_iphdr*)&icmp[1];
|
||||
#else
|
||||
struct icmphdr *icmp = (struct icmphdr *)((char *)ip_hdr + ip_hdr->ihl * 4);
|
||||
struct iphdr *ip_inner = (struct iphdr*)&icmp[1];
|
||||
#endif
|
||||
// ICMP unreach comes from another server (not the one we sent a probe to);
|
||||
// But we will fix up saddr to be who we sent the probe to, in case you care.
|
||||
fs_modify_string(fs, "saddr", make_ip_str(ip_inner->daddr), 1);
|
||||
fs_modify_string(fs, "saddr", make_ip_str(ip_inner->daddr.s_addr), 1);
|
||||
fs_add_string(fs, "classification", (char*) "icmp-unreach", 0);
|
||||
fs_add_uint64(fs, "success", 0);
|
||||
fs_add_null(fs, "sport");
|
||||
fs_add_null(fs, "dport");
|
||||
fs_add_string(fs, "icmp_responder", make_ip_str(ip_hdr->saddr), 1);
|
||||
fs_add_string(fs, "icmp_responder", make_ip_str(ip_hdr->saddr.s_addr), 1);
|
||||
fs_add_uint64(fs, "icmp_type", icmp->type);
|
||||
fs_add_uint64(fs, "icmp_code", icmp->code);
|
||||
if (icmp->code <= ICMP_PREC_CUTOFF) {
|
||||
@ -257,41 +308,71 @@ void udp_process_packet(const u_char *packet, UNUSED uint32_t len, fieldset_t *f
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
int udp_validate_packet(const struct zmap_iphdr *ip_hdr, uint32_t len,
|
||||
#else
|
||||
int udp_validate_packet(const struct iphdr *ip_hdr, uint32_t len,
|
||||
#endif
|
||||
__attribute__((unused))uint32_t *src_ip, uint32_t *validation)
|
||||
{
|
||||
uint16_t dport, sport;
|
||||
if (ip_hdr->protocol == IPPROTO_UDP) {
|
||||
#ifdef __FREEBSD__
|
||||
if ((4*ip_hdr->ihl + sizeof(struct zmap_udphdr)) > len) {
|
||||
#else
|
||||
if ((4*ip_hdr->ihl + sizeof(struct udphdr)) > len) {
|
||||
#endif
|
||||
// buffer not large enough to contain expected udp header
|
||||
return 0;
|
||||
}
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_udphdr *udp = (struct zmap_udphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#else
|
||||
struct udphdr *udp = (struct udphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#endif
|
||||
|
||||
sport = ntohs(udp->dest);
|
||||
dport = ntohs(udp->source);
|
||||
} else if (ip_hdr->protocol == IPPROTO_ICMP) {
|
||||
// UDP can return ICMP Destination unreach
|
||||
// IP( ICMP( IP( UDP ) ) ) for a destination unreach
|
||||
#ifdef __FREEBSD__
|
||||
uint32_t min_len = 4*ip_hdr->ihl + sizeof(struct zmap_icmphdr)
|
||||
+ sizeof(struct zmap_iphdr) + sizeof(struct zmap_udphdr);
|
||||
#else
|
||||
uint32_t min_len = 4*ip_hdr->ihl + sizeof(struct icmphdr)
|
||||
+ sizeof(struct iphdr) + sizeof(struct udphdr);
|
||||
#endif
|
||||
if (len < min_len) {
|
||||
// Not enough information for us to validate
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_icmphdr *icmp = (struct zmap_icmphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#else
|
||||
struct icmphdr *icmp = (struct icmphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
|
||||
#endif
|
||||
if (icmp->type != ICMP_DEST_UNREACH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_inner = (struct zmap_iphdr*)&icmp[1];
|
||||
// Now we know the actual inner ip length, we should recheck the buffer
|
||||
if (len < 4*ip_inner->ihl - sizeof(struct zmap_iphdr) + min_len) {
|
||||
#else
|
||||
struct iphdr *ip_inner = (struct iphdr*)&icmp[1];
|
||||
// Now we know the actual inner ip length, we should recheck the buffer
|
||||
if (len < 4*ip_inner->ihl - sizeof(struct iphdr) + min_len) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
// This is the packet we sent
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_udphdr *udp = (struct zmap_udphdr *)((char*)ip_inner + 4*ip_inner->ihl);
|
||||
#else
|
||||
struct udphdr *udp = (struct udphdr *)((char*)ip_inner + 4*ip_inner->ihl);
|
||||
#endif
|
||||
|
||||
sport = ntohs(udp->source);
|
||||
dport = ntohs(udp->dest);
|
||||
|
@ -12,7 +12,9 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __FREEBSD__
|
||||
#include <netinet/ether.h>
|
||||
#endif
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
@ -24,6 +26,16 @@
|
||||
|
||||
#include "state.h"
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
#include "../proto_headers.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD_INCLUDES__ /* some macros in Linux system headers */
|
||||
#define ETH_ALEN ETHER_ADDR_LEN
|
||||
#define ETH_P_IP ETYPE_IPV4 /* EtherType 0x800 */
|
||||
#endif
|
||||
|
||||
#ifndef __FREEBSD__ /* TODO: */
|
||||
void print_macaddr(struct ifreq* i)
|
||||
{
|
||||
printf("Device %s -> Ethernet %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
@ -35,8 +47,13 @@ void print_macaddr(struct ifreq* i)
|
||||
(int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[4],
|
||||
(int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[5]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void fprintf_ip_header(FILE *fp, struct zmap_iphdr *iph)
|
||||
#else
|
||||
void fprintf_ip_header(FILE *fp, struct iphdr *iph)
|
||||
#endif
|
||||
{
|
||||
struct in_addr *s = (struct in_addr *) &(iph->saddr);
|
||||
struct in_addr *d = (struct in_addr *) &(iph->daddr);
|
||||
@ -53,7 +70,11 @@ void fprintf_ip_header(FILE *fp, struct iphdr *iph)
|
||||
ntohl(iph->check));
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void fprintf_eth_header(FILE *fp, struct zmap_ethhdr *ethh)
|
||||
#else
|
||||
void fprintf_eth_header(FILE *fp, struct ethhdr *ethh)
|
||||
#endif
|
||||
{
|
||||
fprintf(fp, "eth { shost: %02x:%02x:%02x:%02x:%02x:%02x | "
|
||||
"dhost: %02x:%02x:%02x:%02x:%02x:%02x }\n",
|
||||
@ -71,14 +92,22 @@ void fprintf_eth_header(FILE *fp, struct ethhdr *ethh)
|
||||
(int) ((unsigned char *) ethh->h_dest)[5]);
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void make_eth_header(struct zmap_ethhdr *ethh, macaddr_t *src, macaddr_t *dst)
|
||||
#else
|
||||
void make_eth_header(struct ethhdr *ethh, macaddr_t *src, macaddr_t *dst)
|
||||
#endif
|
||||
{
|
||||
memcpy(ethh->h_source, src, ETH_ALEN);
|
||||
memcpy(ethh->h_dest, dst, ETH_ALEN);
|
||||
ethh->h_proto = htons(ETH_P_IP);
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void make_ip_header(struct zmap_iphdr *iph, uint8_t protocol, uint16_t len)
|
||||
#else
|
||||
void make_ip_header(struct iphdr *iph, uint8_t protocol, uint16_t len)
|
||||
#endif
|
||||
{
|
||||
iph->ihl = 5; // Internet Header Length
|
||||
iph->version = 4; // IPv4
|
||||
@ -99,7 +128,23 @@ void make_icmp_header(struct icmp *buf)
|
||||
buf->icmp_code = 0;
|
||||
buf->icmp_seq = 0;
|
||||
}
|
||||
/* TODO: This is sketchy when linking against other translation units.
|
||||
Probably need to reconcile the struct names properly */
|
||||
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void make_tcp_header(struct zmap_tcphdr *tcp_header, port_h_t dest_port)
|
||||
{
|
||||
tcp_header->seq = random();
|
||||
tcp_header->ack_seq = 0;
|
||||
tcp_header->th_flags = 0;
|
||||
tcp_header->th_flags = 5 << 4; /* data offset */
|
||||
tcp_header->th_flags &= TH_SYN;
|
||||
tcp_header->th_win = htons(65535);
|
||||
tcp_header->check = 0;
|
||||
tcp_header->th_urp = 0;
|
||||
tcp_header->dest = (htons(dest_port));
|
||||
#else
|
||||
void make_tcp_header(struct tcphdr *tcp_header, port_h_t dest_port)
|
||||
{
|
||||
tcp_header->seq = random();
|
||||
@ -111,9 +156,14 @@ void make_tcp_header(struct tcphdr *tcp_header, port_h_t dest_port)
|
||||
tcp_header->check = 0;
|
||||
tcp_header->urg_ptr = 0;
|
||||
tcp_header->dest = htons(dest_port);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void make_udp_header(struct zmap_udphdr *udp_header, port_h_t dest_port,
|
||||
#else
|
||||
void make_udp_header(struct udphdr *udp_header, port_h_t dest_port,
|
||||
#endif
|
||||
uint16_t len)
|
||||
{
|
||||
udp_header->dest = htons(dest_port);
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include "state.h"
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
#include "proto_headers.h"
|
||||
#else
|
||||
#include <netinet/ether.h>
|
||||
#endif /* __FREEBSD__ */
|
||||
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
@ -11,17 +16,32 @@
|
||||
|
||||
#define MAX_PACKET_SIZE 4096
|
||||
|
||||
/* wbk - proceed w/ caution here w/ all the sizeof's */
|
||||
|
||||
typedef unsigned short __attribute__((__may_alias__)) alias_unsigned_short;
|
||||
|
||||
void make_eth_header(struct ethhdr *ethh, macaddr_t *src, macaddr_t *dst);
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void make_eth_header(struct zmap_ethhdr *ethh, macaddr_t *src, macaddr_t *dst);
|
||||
void make_ip_header(struct zmap_iphdr *iph, uint8_t, uint16_t);
|
||||
void make_tcp_header(struct zmap_tcphdr*, port_h_t);
|
||||
#else
|
||||
void make_eth_header(struct ethhdr *ethh, macaddr_t *src, macaddr_t *dst);
|
||||
void make_ip_header(struct iphdr *iph, uint8_t, uint16_t);
|
||||
void make_tcp_header(struct tcphdr*, port_h_t);
|
||||
#endif
|
||||
void make_icmp_header(struct icmp *);
|
||||
#ifdef __FREEBSD__
|
||||
void make_udp_header(struct zmap_udphdr *udp_header, port_h_t dest_port,
|
||||
uint16_t len);
|
||||
void fprintf_ip_header(FILE *fp, struct zmap_iphdr *iph);
|
||||
void fprintf_eth_header(FILE *fp, struct zmap_ethhdr *ethh);
|
||||
#else
|
||||
void make_udp_header(struct udphdr *udp_header, port_h_t dest_port,
|
||||
uint16_t len);
|
||||
void fprintf_ip_header(FILE *fp, struct iphdr *iph);
|
||||
void fprintf_eth_header(FILE *fp, struct ethhdr *ethh);
|
||||
#endif
|
||||
|
||||
static inline unsigned short in_checksum(unsigned short *ip_pkt, int len)
|
||||
{
|
||||
@ -37,7 +57,11 @@ static inline unsigned short in_checksum(unsigned short *ip_pkt, int len)
|
||||
__attribute__((unused)) static inline unsigned short ip_checksum(
|
||||
unsigned short *buf)
|
||||
{
|
||||
#ifdef __FREEBSD__
|
||||
return in_checksum(buf, (int) sizeof(struct zmap_iphdr));
|
||||
#else
|
||||
return in_checksum(buf, (int) sizeof(struct iphdr));
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((unused)) static inline unsigned short icmp_checksum(
|
||||
@ -47,7 +71,11 @@ __attribute__((unused)) static inline unsigned short icmp_checksum(
|
||||
}
|
||||
|
||||
static __attribute__((unused)) uint16_t tcp_checksum(unsigned short len_tcp,
|
||||
#ifdef __FREEBSD__
|
||||
uint32_t saddr, uint32_t daddr, struct zmap_tcphdr *tcp_pkt)
|
||||
#else
|
||||
uint32_t saddr, uint32_t daddr, struct tcphdr *tcp_pkt)
|
||||
#endif
|
||||
{
|
||||
alias_unsigned_short *src_addr = (alias_unsigned_short *) &saddr;
|
||||
alias_unsigned_short *dest_addr = (alias_unsigned_short *) &daddr;
|
||||
|
@ -16,7 +16,11 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#ifdef __FREEBSD__
|
||||
#include "../proto_headers.h"
|
||||
#else
|
||||
#include <linux/if_packet.h>
|
||||
#endif
|
||||
|
||||
#include "../../lib/logger.h"
|
||||
#include "../fieldset.h"
|
||||
@ -54,10 +58,14 @@ void print_probe_modules(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void fs_add_ip_fields(fieldset_t *fs, struct zmap_iphdr *ip)
|
||||
#else
|
||||
void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip)
|
||||
#endif
|
||||
{
|
||||
fs_add_string(fs, "saddr", make_ip_str(ip->saddr), 1);
|
||||
fs_add_string(fs, "daddr", make_ip_str(ip->daddr), 1);
|
||||
fs_add_string(fs, "saddr", make_ip_str(ip->saddr.s_addr), 1);
|
||||
fs_add_string(fs, "daddr", make_ip_str(ip->daddr.s_addr), 1);
|
||||
fs_add_uint64(fs, "ipid", ntohs(ip->id));
|
||||
fs_add_uint64(fs, "ttl", ip->ttl);
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#ifndef PROBE_MODULES_H
|
||||
#define PROBE_MODULES_H
|
||||
|
||||
#include "../proto_headers.h"
|
||||
|
||||
typedef struct probe_response_type {
|
||||
const uint8_t is_success;
|
||||
const char *name;
|
||||
@ -20,9 +22,13 @@ typedef int (*probe_make_packet_cb)(void* packetbuf, ipaddr_n_t src_ip,
|
||||
typedef void (*probe_print_packet_cb)(FILE *, void* packetbuf);
|
||||
typedef int (*probe_close_cb)(struct state_conf*,
|
||||
struct state_send*, struct state_recv*);
|
||||
#ifdef __FREEBSD__
|
||||
typedef int (*probe_validate_packet_cb)(const struct zmap_iphdr *ip_hdr,
|
||||
uint32_t len, uint32_t *src_ip, uint32_t *validation);
|
||||
#else
|
||||
typedef int (*probe_validate_packet_cb)(const struct iphdr *ip_hdr,
|
||||
uint32_t len, uint32_t *src_ip, uint32_t *validation);
|
||||
|
||||
#endif
|
||||
typedef void (*probe_classify_packet_cb)(const u_char* packetbuf,
|
||||
uint32_t len, fieldset_t*);
|
||||
|
||||
@ -51,7 +57,11 @@ typedef struct probe_module {
|
||||
|
||||
probe_module_t* get_probe_module_by_name(const char*);
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
void fs_add_ip_fields(fieldset_t *fs, struct zmap_iphdr *ip);
|
||||
#else
|
||||
void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip);
|
||||
#endif
|
||||
void fs_add_system_fields(fieldset_t *fs, int is_repeat, int in_cooldown);
|
||||
void print_probe_modules(void);
|
||||
|
||||
|
174
src/proto_headers.h
Normal file
174
src/proto_headers.h
Normal file
@ -0,0 +1,174 @@
|
||||
#ifndef HEADER_PROTO_HEADERS_H
|
||||
#define HEADER_PROTO_HEADERS_H
|
||||
/* struct definitions for accessing frames and packets */
|
||||
|
||||
/* Initially copied from Tim Carsten's "sniffex" example from tcpdump.org.
|
||||
Macros are all that remain. Though it's almost 100% modified,
|
||||
here is his permissive license to be on the safe side: */
|
||||
|
||||
/* This document is Copyright 2002 Tim Carstens. All rights reserved.
|
||||
Redistribution and use, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
Redistribution must retain the above copyright notice and this
|
||||
list of conditions.
|
||||
The name of Tim Carstens may not be used to endorse or promote
|
||||
products derived from this document without specific prior
|
||||
written permission. */
|
||||
/*
|
||||
****************************************************************************
|
||||
*
|
||||
* This software is a modification of Tim Carstens' "sniffer.c"
|
||||
* demonstration source code, released as follows:
|
||||
*
|
||||
* sniffer.c
|
||||
* Copyright (c) 2002 Tim Carstens
|
||||
* 2002-01-07
|
||||
* Demonstration of using libpcap
|
||||
* timcarst -at- yahoo -dot- com
|
||||
*
|
||||
* "sniffer.c" is distributed under these terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. The name "Tim Carstens" may not be used to endorse or promote
|
||||
* products derived from this software without prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* <end of "sniffer.c" terms>
|
||||
*/
|
||||
|
||||
//#include <sys/types.h> /* for u_char, uint16_t and the like */
|
||||
#include <stdint.h> /* for u_char, uint16_t and the like */
|
||||
#include <netinet/in.h> /* for in_addr */
|
||||
//#include <netinet/tcp.h> /* for tcp_seq */ /* TODO: get it out? too dangerous? */
|
||||
|
||||
/* Macros that may already exist on Linux but not other platforms. */
|
||||
/* Ethernet addresses are 6 bytes */
|
||||
#ifndef ETHER_ADDR_LEN
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#endif
|
||||
#ifndef ETHER_HDR_LEN
|
||||
#define ETHER_HDR_LEN 14 /* wbk - adding to avoid sizeof(sniff_ethernet) */
|
||||
#endif
|
||||
#ifndef IFHWADDRLEN
|
||||
#define IFHWADDRLEN ETHER_ADDR_LEN
|
||||
#endif
|
||||
|
||||
struct zmap_ethhdr {
|
||||
u_char h_dest[ETHER_ADDR_LEN];
|
||||
u_char h_source[ETHER_ADDR_LEN];
|
||||
uint16_t h_proto;
|
||||
#define ETYPE_IPV4 0x0800
|
||||
#define ETYPE_IPV6 0x86dd
|
||||
#define ETYPE_ARP 0x0806
|
||||
#define ETYPE_RARP 0x8035
|
||||
};
|
||||
|
||||
struct zmap_iphdr {
|
||||
/* wbk TODO: This bitfield stuff will almost certainly need to go, but will
|
||||
complicate client code. */
|
||||
u_char ihl:4,
|
||||
version:4;
|
||||
u_char tos;
|
||||
uint16_t tot_len;
|
||||
uint16_t id;
|
||||
uint16_t frag_off;
|
||||
u_char ttl;
|
||||
u_char protocol;
|
||||
uint16_t check;
|
||||
struct in_addr saddr, daddr;
|
||||
#define IP_FLAGMASK 0xe000 /* flags are first 3 bits of ip_off - wbk */
|
||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
|
||||
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
|
||||
|
||||
};
|
||||
|
||||
struct zmap_tcphdr { /* TODO: maybe change to zmap_tcphdr?*/
|
||||
uint16_t source; /* source port */
|
||||
uint16_t dest; /* destination port */
|
||||
uint32_t seq; /* sequence number */ /*TODO type tcp_seq? */
|
||||
uint32_t ack_seq; /* acknowledgement number */
|
||||
|
||||
u_char th_offx2; /* data offset, rsvd */
|
||||
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
|
||||
u_char th_flags;
|
||||
#define TH_FIN 0x01
|
||||
#define TH_SYN 0x02
|
||||
#define TH_RST 0x04
|
||||
#define TH_PUSH 0x08
|
||||
#define TH_ACK 0x10
|
||||
#define TH_URG 0x20
|
||||
#define TH_ECE 0x40
|
||||
#define TH_CWR 0x80
|
||||
#ifndef TH_FLAGS /* wbk - FreeBSD has equivalent in netinet/tcp.h */
|
||||
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
|
||||
#endif
|
||||
uint16_t th_win; /* window */
|
||||
uint16_t check; /* checksum */
|
||||
uint16_t th_urp; /* urgent pointer */
|
||||
};
|
||||
|
||||
struct zmap_udphdr {
|
||||
uint16_t source;
|
||||
uint16_t dest;
|
||||
uint16_t len;
|
||||
uint16_t check;
|
||||
};
|
||||
|
||||
#ifndef ICMP_HDR_LEN
|
||||
#define ICMP_HDR_LEN 64
|
||||
#endif
|
||||
struct zmap_icmphdr {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t checksum;
|
||||
/*uint16_t id; / * this part is different for different ICMP services * /
|
||||
uint16_t seq; */
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo;
|
||||
uint32_t gateway;
|
||||
struct { // TODO: check this. Perfect overlap causing warnings?
|
||||
uint16_t __unused;
|
||||
uint16_t mtu;
|
||||
} frag;
|
||||
} un;
|
||||
#ifndef ICMP_ECHO
|
||||
#define ICMP_ECHO 8
|
||||
#endif
|
||||
#ifndef ICMP_ECHOREPLY
|
||||
#define ICMP_ECHOREPLY 0
|
||||
#endif
|
||||
#ifndef ICMP_TIME_EXCEEDED
|
||||
#define ICMP_TIME_EXCEEDED 11
|
||||
#endif
|
||||
#ifndef ICMP_DEST_UNREACH
|
||||
#define ICMP_DEST_UNREACH 3
|
||||
#endif
|
||||
#ifndef ICMP_PREC_CUTOFF
|
||||
#define ICMP_PREC_CUTOFF 15
|
||||
#endif
|
||||
};
|
||||
#endif /* HEADER_PROTO_HEADERS_H */
|
41
src/recv.c
41
src/recv.c
@ -16,12 +16,17 @@
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h> /* wbk BSD requires netinet/in.h and ip.h first */
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
#include "proto_headers.h"
|
||||
#define ETH_P_IP ETYPE_IPV4
|
||||
#else
|
||||
#include <linux/if_ether.h>
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@ -76,21 +81,41 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
|
||||
// length of entire packet captured by libpcap
|
||||
uint32_t buflen = (uint32_t) p->caplen;
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
if ((sizeof(struct zmap_iphdr) + (zconf.send_ip_pkts ? 0 : sizeof(struct zmap_ethhdr))) > buflen) {
|
||||
#else
|
||||
if ((sizeof(struct iphdr) + (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))) > buflen) {
|
||||
#endif
|
||||
// buffer not large enough to contain ethernet
|
||||
// and ip headers. further action would overrun buf
|
||||
return;
|
||||
}
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_iphdr *ip_hdr = (struct zmap_iphdr *)&bytes[(zconf.send_ip_pkts ? 0 : sizeof(struct zmap_ethhdr))];
|
||||
#else
|
||||
struct iphdr *ip_hdr = (struct iphdr *)&bytes[(zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))];
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD__ /* TODO: this change might work on Linux; is cleaner */
|
||||
uint32_t src_ip = ip_hdr->saddr.s_addr;
|
||||
#else
|
||||
uint32_t src_ip = ip_hdr->saddr;
|
||||
#endif
|
||||
|
||||
uint32_t validation[VALIDATE_BYTES/sizeof(uint8_t)];
|
||||
// TODO: for TTL exceeded messages, ip_hdr->saddr is going to be different
|
||||
// and we must calculate off potential payload message instead
|
||||
#ifdef __FREEBSD__
|
||||
validate_gen(ip_hdr->daddr.s_addr, ip_hdr->saddr.s_addr, (uint8_t *)validation);
|
||||
#else
|
||||
validate_gen(ip_hdr->daddr, ip_hdr->saddr, (uint8_t *)validation);
|
||||
#endif
|
||||
|
||||
#ifdef __FREEBSD__
|
||||
if (!zconf.probe_module->validate_packet(ip_hdr, buflen - (zconf.send_ip_pkts ? 0 : sizeof(struct zmap_ethhdr)),
|
||||
#else
|
||||
if (!zconf.probe_module->validate_packet(ip_hdr, buflen - (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr)),
|
||||
#endif
|
||||
&src_ip, validation)) {
|
||||
return;
|
||||
}
|
||||
@ -108,7 +133,11 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
|
||||
if (buflen > sizeof(fake_eth_hdr)) {
|
||||
buflen = sizeof(fake_eth_hdr);
|
||||
}
|
||||
memcpy(&fake_eth_hdr[sizeof(struct ethhdr)], bytes, buflen);
|
||||
#ifdef __FREEBSD__
|
||||
memcpy(&fake_eth_hdr[sizeof(struct zmap_ethhdr)], bytes, buflen); /* wbk TODO: replace these sizeof(struct *hdr) with macros) */
|
||||
#else
|
||||
memcpy(&fake_eth_hdr[sizeof(struct ethhdr)], bytes, buflen); /* wbk TODO: replace these sizeof(struct *hdr) with macros) */
|
||||
#endif
|
||||
bytes = fake_eth_hdr;
|
||||
}
|
||||
zconf.probe_module->process_packet(bytes, buflen, fs);
|
||||
@ -198,7 +227,11 @@ int recv_run(pthread_mutex_t *recv_ready_mutex)
|
||||
}
|
||||
}
|
||||
if (zconf.send_ip_pkts) {
|
||||
#ifdef __FREEBSD__
|
||||
struct zmap_ethhdr *eth = (struct zmap_ethhdr *)fake_eth_hdr;
|
||||
#else
|
||||
struct ethhdr *eth = (struct ethhdr *)fake_eth_hdr;
|
||||
#endif
|
||||
memset(fake_eth_hdr, 0, sizeof(fake_eth_hdr));
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
}
|
||||
|
144
src/send.c
144
src/send.c
@ -19,10 +19,27 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __FREEBSD_INCLUDES__
|
||||
#include <pcap/pcap.h> /* TODO:other BSD's*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if_dl.h> /* for sockaddr_dl */
|
||||
/* beware, defined in other modulkes */
|
||||
#define PCAP_PROMISC 1
|
||||
#define PCAP_TIMEOUT 1000
|
||||
#else /* TODO double check this */
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
|
||||
/* might want to change to ifdef __LINUX__. Will help more than just FreeBSD */
|
||||
#ifdef __FREEBSD_INCLUDES__
|
||||
#include "proto_headers.h"
|
||||
#else
|
||||
#include <linux/if_packet.h>
|
||||
#endif /* __FREEBSD__ */
|
||||
|
||||
#include "../lib/logger.h"
|
||||
#include "../lib/random.h"
|
||||
@ -132,6 +149,93 @@ int send_init(void)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
pcap_t* get_pcap_t(void)
|
||||
{
|
||||
pcap_t *pc = NULL;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
/* wbk return a pcap_t ready for pcap_inject */
|
||||
log_debug("send", "getting pcap handle");
|
||||
/* snaplen of 0 since we only write on this pcpa_t? */
|
||||
pc = pcap_open_live(zconf.iface, 0,
|
||||
PCAP_PROMISC, /* needed?*/
|
||||
PCAP_TIMEOUT,
|
||||
errbuf);
|
||||
if (pc == NULL) {
|
||||
log_fatal("send", "couldn't open device %s:, %s. "
|
||||
"Do you have permissions for the device?",
|
||||
zconf.iface, errbuf);
|
||||
}
|
||||
/*struct bpf_program bpf;
|
||||
//if (pcap_compile(pc, &bpf, zconf.probe_module->pcap_filter, 1, 0) < 0) {
|
||||
if (pcap_compile(pc, &bpf, zconf.probe_module->pcap_filter, 1, PCAP_NETMASK_UNKNOWN) < 0) {
|
||||
log_debug("send", "pcap_filter failed. Tried \"%s\"",
|
||||
zconf.probe_module->pcap_filter);
|
||||
log_fatal("send", "couldn't compile filter");
|
||||
}
|
||||
if (pcap_setfilter(pc, &bpf) < 0) {
|
||||
log_fatal("send", "couldn't install filter");
|
||||
}*/
|
||||
log_debug("send", "injector ready");
|
||||
return pc;
|
||||
}
|
||||
|
||||
static void get_hwaddr(unsigned char *hwaddr) /* TODO determine ret type etc -wbk**/
|
||||
/* error return or rely on log_fatal? TODO*/
|
||||
{
|
||||
/* pass a pointer to ETHER_ADDR_LEN bytes. */
|
||||
/* double check that interface name gets validated since
|
||||
we use strcmp here. Unless there's some POSIX ocnstant for
|
||||
max iface name (doubt it) IFNAMESIZ? */
|
||||
struct ifaddrs *p = NULL;
|
||||
struct sockaddr_dl* sdl = NULL; /* BSD-specific hardware address */
|
||||
|
||||
if (getifaddrs(&p) == -1) {
|
||||
log_fatal("send", "get_hwaddr() getifaddrs() failed!");
|
||||
/* TODO: strerror() */
|
||||
|
||||
}
|
||||
for (;p != NULL; p = p->ifa_next) {
|
||||
if ( (p->ifa_addr->sa_family == AF_LINK) /* linux would need AF_PACKET */
|
||||
&& (strncmp(zconf.iface, p->ifa_name, IF_NAMESIZE) == 0) )
|
||||
{
|
||||
/* copy MAC. Or get the whole sockaddr :). Eliminate sizeof()? */
|
||||
/* Linux has sockaddr_ll. BSD has sockaddr_dl. structs are differnent */
|
||||
/* let's just get the hardware address to pass back. */
|
||||
sdl = (struct sockaddr_dl*)(p->ifa_addr);
|
||||
if (sdl->sdl_alen == ETHER_ADDR_LEN) /* paranoia */
|
||||
memcpy(hwaddr, LLADDR((sdl)), sdl->sdl_alen);
|
||||
else
|
||||
log_fatal("send", "gethwaddr() unexpected sdl_alen!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*static void get_ipaddr(struct sockaddr *sa)*/
|
||||
/* TODO: Is this even needed? */
|
||||
static void get_ipaddr(struct in_addr *in)
|
||||
{
|
||||
/* retrieve IPaddress using getifaddrs(), used by caller to craft packet for
|
||||
pcap_inject(). TODO:see how nmap handles this. */
|
||||
struct ifaddrs *p = NULL;
|
||||
struct sockaddr_in *sin = NULL;
|
||||
if (getifaddrs(&p) == -1) {
|
||||
log_fatal("send", "get_ipaddr() getifaddrs() failed!");
|
||||
}
|
||||
for (; p != NULL; p = p->ifa_next) {
|
||||
if ( (p->ifa_addr->sa_family == AF_INET)
|
||||
&& (strncmp(zconf.iface, p->ifa_name, IF_NAMESIZE) == 0) )
|
||||
{
|
||||
/* TODO: grab IPs a struct sockaddr_in I guess */
|
||||
sin = (struct sockaddr_in *)(p->ifa_addr);
|
||||
/* copy the struct in_addr for return*/
|
||||
/* TODO: Idon't like using sizeof() macro; see if there's a better alternative. */
|
||||
/* TODO:sanity check here? */
|
||||
memcpy(in, &(sin->sin_addr), sizeof(struct in_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
int get_socket(void)
|
||||
{
|
||||
int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
@ -141,6 +245,7 @@ int get_socket(void)
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_dryrun_socket(void)
|
||||
{
|
||||
@ -167,11 +272,27 @@ static inline ipaddr_n_t get_src_ip(ipaddr_n_t dst, int local_offset)
|
||||
}
|
||||
|
||||
// one sender thread
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
int send_run(pcap_t *pc)
|
||||
#else
|
||||
int send_run(int sock)
|
||||
#endif
|
||||
{
|
||||
log_debug("send", "thread started");
|
||||
pthread_mutex_lock(&send_mutex);
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
/* Using pcap, mirror the linux SOCK_RAW behaviour as closely
|
||||
as possible */
|
||||
unsigned char mac[ETHER_ADDR_LEN];
|
||||
struct in_addr src_ip = {0};
|
||||
//pcap_t *pc = get_pcap_t();
|
||||
/* We don't need the index; we have a pcap handle to the proper
|
||||
interface */
|
||||
get_hwaddr(mac);
|
||||
get_ipaddr(&src_ip);
|
||||
|
||||
#else
|
||||
//int sock = get_socket();
|
||||
struct sockaddr_ll sockaddr;
|
||||
// get source interface index
|
||||
struct ifreq if_idx;
|
||||
@ -181,7 +302,7 @@ int send_run(int sock)
|
||||
zconf.iface);
|
||||
return -1;
|
||||
}
|
||||
strncpy(if_idx.ifr_name, zconf.iface, IFNAMSIZ-1);
|
||||
strncpy(if_idx.ifr_name, zconf.iface, IFNAMSIZ-2);
|
||||
if (ioctl(sock, SIOCGIFINDEX, &if_idx) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
return -1;
|
||||
@ -206,16 +327,23 @@ int send_run(int sock)
|
||||
perror("SIOCGIFADDR");
|
||||
return -1;
|
||||
}
|
||||
// wbk TODO: gateway MAC.
|
||||
// destination address for the socket
|
||||
memset((void*) &sockaddr, 0, sizeof(struct sockaddr_ll));
|
||||
sockaddr.sll_ifindex = ifindex;
|
||||
sockaddr.sll_halen = ETH_ALEN;
|
||||
memcpy(sockaddr.sll_addr, zconf.gw_mac, ETH_ALEN);
|
||||
|
||||
#endif /* not ZMAP_PCAP_INJECT */ /* may move down... TODO wbk */
|
||||
|
||||
char buf[MAX_PACKET_SIZE];
|
||||
memset(buf, 0, MAX_PACKET_SIZE);
|
||||
zconf.probe_module->thread_initialize(buf,
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
mac,
|
||||
#else
|
||||
(unsigned char *)if_mac.ifr_hwaddr.sa_data,
|
||||
#endif
|
||||
zconf.gw_mac, zconf.target_port);
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
|
||||
@ -288,6 +416,19 @@ int send_run(int sock)
|
||||
zconf.probe_module->print_packet(stdout, buf);
|
||||
} else {
|
||||
int l = zconf.probe_module->packet_length;
|
||||
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
int rc = pcap_inject(pc, buf, (size_t)l);
|
||||
if (rc == -1) {
|
||||
struct in_addr addr;
|
||||
addr.s_addr = curr;
|
||||
log_fatal("send", "pcap_inject() failed for %s. %s", /* TODO: make log_debug */
|
||||
inet_ntoa(addr), strerror(errno));
|
||||
pthread_mutex_lock(&send_mutex);
|
||||
zsend.sendto_failures++;
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
}
|
||||
#else /* TODO: error handling can be shared. */
|
||||
int rc = sendto(sock, buf + zconf.send_ip_pkts*sizeof(struct ethhdr),
|
||||
l, 0,
|
||||
(struct sockaddr *)&sockaddr,
|
||||
@ -301,6 +442,7 @@ int send_run(int sock)
|
||||
zsend.sendto_failures++;
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
src/send.h
24
src/send.h
@ -9,9 +9,33 @@
|
||||
#ifndef SEND_H
|
||||
#define SEND_H
|
||||
|
||||
#include <stdint.h> /* for uintptr_t ? */
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
#include <pcap/pcap.h>
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* wrapper for Linux socket handle or pcap_t. BSD port uses
|
||||
pcap_inject() instead of Linux SOCK_RAW sendto().
|
||||
This is an ugly hack. Client code will need to check
|
||||
zconf for dryrun, and if ZMAP_PCAP_INJECT, use pcap_t,
|
||||
otherwise sock.*/
|
||||
struct send_handle {
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
pcap_t *pc;
|
||||
#endif
|
||||
//int sock;
|
||||
uintptr_t sock;
|
||||
};
|
||||
|
||||
int get_socket(void);
|
||||
int get_dryrun_socket(void);
|
||||
int send_init(void);
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
pcap_t *get_pcap_t(void);
|
||||
int send_run(pcap_t *pc);
|
||||
#else
|
||||
int send_run(int);
|
||||
#endif
|
||||
|
||||
#endif //SEND_H
|
||||
|
16
src/state.h
16
src/state.h
@ -8,10 +8,20 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#ifdef __FREEBSD_INCLUDES__
|
||||
/* wbk TODO: Might just conditionally include ip.h if on Linux. Might not
|
||||
need netinet/ip.h once we have out handrolled structs for protocol headers */
|
||||
#include <sys/types.h>
|
||||
#include "proto_headers.h" // for IFHWADDR only
|
||||
|
||||
#else /* wbk TODO examine CPP logic a bit more... might be cleaner */
|
||||
#include <netinet/ether.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if.h> // for IFHWADDR
|
||||
#endif /* __FREEBSD_INCLUDES__ */
|
||||
|
||||
//#include <netinet/ip.h> // wbk - doesn't seem to be needed
|
||||
//#include <netinet/tcp.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "fieldset.h"
|
||||
|
39
src/zmap.c
39
src/zmap.c
@ -27,6 +27,10 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __FREEBSD_INCLUDES__
|
||||
#include <pthread_np.h> /* per man PTHREAD_AFFINITY_NP(3) */
|
||||
#endif
|
||||
|
||||
#include "../lib/logger.h"
|
||||
#include "../lib/random.h"
|
||||
|
||||
@ -79,11 +83,15 @@ static void set_cpu(void)
|
||||
pthread_mutex_lock(&cpu_affinity_mutex);
|
||||
static int core=0;
|
||||
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#ifdef __FREEBSD_PTHREADS__
|
||||
cpuset_t cpuset;
|
||||
#else
|
||||
cpu_set_t cpuset;
|
||||
#endif
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(core, &cpuset);
|
||||
if (pthread_setaffinity_np(pthread_self(),
|
||||
sizeof(cpu_set_t), &cpuset) != 0) {
|
||||
sizeof(cpuset), &cpuset) != 0) {
|
||||
log_error("zmap", "can't set thread CPU affinity");
|
||||
}
|
||||
log_trace("zmap", "set thread %u affinity to core %d",
|
||||
@ -94,10 +102,21 @@ static void set_cpu(void)
|
||||
|
||||
static void* start_send(void *arg)
|
||||
{
|
||||
uintptr_t v = (uintptr_t) arg;
|
||||
/* TODO: This is really ugly. */
|
||||
/* keep in mind this is all pointing at the caller's stack copy of this
|
||||
struct. If we let zmap_start return before threads die, or if we modify
|
||||
the members within the worker threads, this will need to be changed.
|
||||
Should be ok, if ugly, as long as access is read-only and calling function
|
||||
doesn't return early, leaving this pointer pointing out of the stack */
|
||||
struct send_handle *handle = (struct send_handle *) arg;
|
||||
uintptr_t v = handle->sock;
|
||||
int sock = (int) v & 0xFFFF;
|
||||
set_cpu();
|
||||
send_run(sock);
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
send_run(handle->pc);
|
||||
#else
|
||||
send_run(handle->sock);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -253,14 +272,20 @@ static void start_zmap(void)
|
||||
assert(tsend);
|
||||
log_debug("zmap", "using %d sender threads", zconf.senders);
|
||||
for (int i=0; i < zconf.senders; i++) {
|
||||
uintptr_t sock;
|
||||
//uintptr_t sock;
|
||||
struct send_handle handle = {0,NULL};
|
||||
if (zconf.dryrun) {
|
||||
sock = get_dryrun_socket();
|
||||
handle.sock = get_dryrun_socket();
|
||||
} else {
|
||||
sock = get_socket();
|
||||
#ifdef ZMAP_PCAP_INJECT
|
||||
handle.pc = get_pcap_t();
|
||||
#else
|
||||
handle.sock = get_socket();
|
||||
#endif
|
||||
}
|
||||
|
||||
int r = pthread_create(&tsend[i], NULL, start_send, (void*) sock);
|
||||
//int r = pthread_create(&tsend[i], NULL, start_send, (void*) sock);
|
||||
int r = pthread_create(&tsend[i], NULL, start_send, (void*) &handle);
|
||||
if (r != 0) {
|
||||
log_fatal("zmap", "unable to create send thread");
|
||||
exit(EXIT_FAILURE);
|
||||
|
Loading…
Reference in New Issue
Block a user