391 lines
9.0 KiB
C
391 lines
9.0 KiB
C
/*
|
|
* $smu-mark$
|
|
* $name: main.c$
|
|
* $author: Salvatore Sanfilippo <antirez@invece.org>$
|
|
* $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$
|
|
* $license: This software is under GPL version 2 of license$
|
|
* $date: Fri Nov 5 11:55:48 MET 1999$
|
|
* $rev: 8$
|
|
*/
|
|
|
|
/*
|
|
* hping official page at http://www.kyuzz.org/antirez
|
|
* Covered by GPL version 2, Read the COPYING file for more information
|
|
*/
|
|
|
|
/* $Id: main.c,v 1.26 2003/08/07 23:55:55 antirez Exp $ */
|
|
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
|
|
#include "hping2.h"
|
|
|
|
#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP)
|
|
#include <pcap.h>
|
|
#endif /* ! OSTYPE_LINUX || FORCE_LIBPCAP */
|
|
|
|
/* globals */
|
|
unsigned int
|
|
tcp_th_flags = 0,
|
|
linkhdr_size = -1, /* physical layer header size */
|
|
ip_tos = 0,
|
|
set_seqnum = FALSE,
|
|
tcp_seqnum = FALSE,
|
|
set_ack,
|
|
h_if_mtu,
|
|
virtual_mtu = DEFAULT_VIRTUAL_MTU,
|
|
ip_frag_offset = 0,
|
|
signlen,
|
|
lsr_length = 0,
|
|
ssr_length = 0,
|
|
tcp_ack;
|
|
|
|
|
|
unsigned short int
|
|
data_size = 0;
|
|
|
|
float
|
|
rtt_min = 0,
|
|
rtt_max = 0,
|
|
rtt_avg = 0;
|
|
|
|
int
|
|
sockpacket,
|
|
sockraw,
|
|
sent_pkt = 0,
|
|
recv_pkt = 0,
|
|
out_of_sequence_pkt = 0,
|
|
sending_wait = DEFAULT_SENDINGWAIT, /* see DEFAULT_SENDINGWAIT */
|
|
opt_rawipmode = FALSE,
|
|
opt_icmpmode = FALSE,
|
|
opt_udpmode = FALSE,
|
|
opt_scanmode = FALSE,
|
|
opt_listenmode = FALSE,
|
|
opt_waitinusec = FALSE,
|
|
opt_numeric = FALSE,
|
|
opt_gethost = TRUE,
|
|
opt_quiet = FALSE,
|
|
opt_relid = FALSE,
|
|
opt_fragment = FALSE,
|
|
opt_df = FALSE,
|
|
opt_mf = FALSE,
|
|
opt_debug = FALSE,
|
|
opt_verbose = FALSE,
|
|
opt_winid_order = FALSE,
|
|
opt_keepstill = FALSE,
|
|
opt_datafromfile= FALSE,
|
|
opt_hexdump = FALSE,
|
|
opt_contdump = FALSE,
|
|
opt_sign = FALSE,
|
|
opt_safe = FALSE,
|
|
opt_end = FALSE,
|
|
opt_traceroute = FALSE,
|
|
opt_seqnum = FALSE,
|
|
opt_incdport = FALSE,
|
|
opt_force_incdport = FALSE,
|
|
opt_icmptype = DEFAULT_ICMP_TYPE,
|
|
opt_icmpcode = DEFAULT_ICMP_CODE,
|
|
opt_rroute = FALSE,
|
|
opt_tcpexitcode = FALSE,
|
|
opt_badcksum = FALSE,
|
|
opt_tr_keep_ttl = FALSE,
|
|
opt_tcp_timestamp = FALSE,
|
|
opt_tr_stop = FALSE,
|
|
opt_tr_no_rtt = FALSE,
|
|
opt_rand_dest = FALSE,
|
|
opt_rand_source = FALSE,
|
|
opt_lsrr = FALSE,
|
|
opt_ssrr = FALSE,
|
|
opt_cplt_rte = FALSE,
|
|
opt_bps = 0,
|
|
opt_pps = 0,
|
|
tcp_exitcode = 0,
|
|
src_ttl = DEFAULT_TTL,
|
|
src_id = -1, /* random */
|
|
base_dst_port = DEFAULT_DPORT,
|
|
dst_port = DEFAULT_DPORT,
|
|
src_port,
|
|
sequence = 0,
|
|
initsport = DEFAULT_INITSPORT,
|
|
src_winsize = DEFAULT_SRCWINSIZE,
|
|
src_thoff = (TCPHDR_SIZE >> 2),
|
|
count = DEFAULT_COUNT,
|
|
ctrlzbind = DEFAULT_BIND,
|
|
delaytable_index= 0,
|
|
eof_reached = FALSE,
|
|
icmp_ip_version = DEFAULT_ICMP_IP_VERSION,
|
|
icmp_ip_ihl = DEFAULT_ICMP_IP_IHL,
|
|
icmp_ip_tos = DEFAULT_ICMP_IP_TOS,
|
|
icmp_ip_tot_len = DEFAULT_ICMP_IP_TOT_LEN,
|
|
icmp_ip_id = DEFAULT_ICMP_IP_ID,
|
|
icmp_ip_protocol= DEFAULT_ICMP_IP_PROTOCOL,
|
|
icmp_ip_srcport = DEFAULT_DPORT,
|
|
icmp_ip_dstport = DEFAULT_DPORT,
|
|
opt_force_icmp = FALSE,
|
|
icmp_cksum = DEFAULT_ICMP_CKSUM,
|
|
raw_ip_protocol = DEFAULT_RAW_IP_PROTOCOL,
|
|
opt_ipv6 = FALSE,
|
|
opt_af = AF_INET,
|
|
opt_flood = FALSE;
|
|
|
|
char
|
|
datafilename [1024],
|
|
targetname [1024],
|
|
targetstraddr [1024],
|
|
ifname [1024] = {'\0'},
|
|
ifstraddr [1024],
|
|
spoofaddr [1024],
|
|
icmp_ip_srcip [1024],
|
|
icmp_ip_dstip [1024],
|
|
icmp_gwip [1024],
|
|
sign [1024],
|
|
rsign [1024], /* reverse sign (hping -> gniph) */
|
|
ip_opt [40],
|
|
*opt_scanports = "";
|
|
|
|
unsigned char
|
|
lsr [255] = {0},
|
|
ssr [255] = {0};
|
|
|
|
unsigned
|
|
ip_optlen = 0;
|
|
|
|
struct sockaddr_in
|
|
icmp_ip_src,
|
|
icmp_ip_dst,
|
|
icmp_gw;
|
|
struct SOCKADDR
|
|
local,
|
|
remote;
|
|
|
|
struct itimerval usec_delay;
|
|
volatile struct delaytable_element delaytable[TABLESIZE];
|
|
|
|
struct hcmphdr *hcmphdr_p; /* global pointer used by send_hcmp to transfer
|
|
hcmp headers to data_handler */
|
|
|
|
#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP)
|
|
pcap_t *pcapfp;
|
|
char errbuf[PCAP_ERRBUF_SIZE];
|
|
struct pcap_pkthdr hdr;
|
|
#endif /* ! OSTYPE_LINUX || FORCE_LIBPCAP */
|
|
|
|
/* main */
|
|
int main(int argc, char **argv)
|
|
{
|
|
char setflags[1024] = {'\0'};
|
|
int c, hdr_size;
|
|
|
|
if (parse_options(argc, argv) == -1) {
|
|
printf("hping3: missing host argument\n"
|
|
"Try `hping3 --help' for more information.\n");
|
|
exit(1);
|
|
}
|
|
|
|
/* reverse sign */
|
|
if (opt_sign || opt_listenmode) {
|
|
char *src = sign+strlen(sign)-1; /* last char before '\0' */
|
|
char *dst = rsign;
|
|
|
|
while(src>=sign)
|
|
*dst++ = *src--;
|
|
*dst = '\0';
|
|
if (opt_debug)
|
|
printf("DEBUG: reverse sign: %s\n", rsign);
|
|
}
|
|
|
|
/* get target address before interface processing */
|
|
if (opt_ipv6)
|
|
resolve6((struct sockaddr*)&remote, targetname);
|
|
else if ((!opt_listenmode && !opt_safe) && !opt_rand_dest)
|
|
resolve((struct sockaddr*)&remote, targetname);
|
|
|
|
if (opt_rand_dest) {
|
|
strlcpy(targetstraddr, targetname, sizeof(targetstraddr));
|
|
} else {
|
|
inet_ntop(opt_af, ADDR(&remote), targetstraddr, sizeof(targetstraddr));
|
|
}
|
|
|
|
/* get interface's name and address */
|
|
if ( get_if_name() == -1 ) {
|
|
printf("[main] no such device\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (opt_verbose || opt_debug) {
|
|
printf("using %s, addr: %s, MTU: %d\n",
|
|
ifname, ifstraddr, h_if_mtu);
|
|
}
|
|
|
|
/* open raw socket */
|
|
sockraw = open_sockraw();
|
|
if (sockraw == -1) {
|
|
printf("[main] can't open raw socket\n");
|
|
exit(1);
|
|
}
|
|
|
|
/* set SO_BROADCAST option */
|
|
socket_broadcast(sockraw);
|
|
/* set SO_IPHDRINCL option */
|
|
if(!opt_ipv6)
|
|
socket_iphdrincl(sockraw);
|
|
|
|
/* open sock packet or libpcap socket */
|
|
#if (defined OSTYPE_LINUX) && (!defined FORCE_LIBPCAP)
|
|
sockpacket = open_sockpacket();
|
|
if (sockpacket == -1) {
|
|
printf("[main] can't open packet socket\n");
|
|
exit(1);
|
|
}
|
|
#else
|
|
if (open_pcap() == -1) {
|
|
printf("[main] open_pcap failed\n");
|
|
exit(1);
|
|
}
|
|
#endif /* OSTYPE_LINUX && !FORCE_LIBPCAP */
|
|
|
|
/* get physical layer header size */
|
|
if (linkhdr_size == -1 && get_linkhdr_size(ifname) == -1) {
|
|
printf("[main] physical layer header size unknown (try --lhs)\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (spoofaddr[0] != '\0')
|
|
{
|
|
if(opt_ipv6)
|
|
resolve6((struct sockaddr*)&local, spoofaddr);
|
|
else
|
|
resolve((struct sockaddr*)&local, spoofaddr);
|
|
}
|
|
|
|
if (icmp_ip_srcip[0] == '\0')
|
|
resolve((struct sockaddr*)&icmp_ip_src, "1.2.3.4");
|
|
else
|
|
resolve((struct sockaddr*)&icmp_ip_src, icmp_ip_srcip);
|
|
|
|
if (icmp_ip_dstip[0] == '\0')
|
|
resolve((struct sockaddr*)&icmp_ip_dst, "5.6.7.8");
|
|
else
|
|
resolve((struct sockaddr*)&icmp_ip_dst, icmp_ip_dstip);
|
|
|
|
if (icmp_gwip[0] == '\0')
|
|
resolve((struct sockaddr*)&icmp_gw, "0.0.0.0");
|
|
else
|
|
resolve((struct sockaddr*)&icmp_gw, icmp_gwip);
|
|
|
|
srand(time(NULL));
|
|
|
|
/* set initial source port */
|
|
if (initsport == -1)
|
|
initsport = src_port = 1024 + (rand() % 2000);
|
|
else
|
|
src_port = initsport;
|
|
|
|
for (c = 0; c < TABLESIZE; c++)
|
|
delaytable[c].seq = -1;
|
|
|
|
/* use SIGALRM to send packets like ping do */
|
|
Signal(SIGALRM, send_packet);
|
|
|
|
/* binding */
|
|
if (ctrlzbind != BIND_NONE) Signal(SIGTSTP, inc_destparm);
|
|
Signal(SIGINT, print_statistics);
|
|
Signal(SIGTERM, print_statistics);
|
|
|
|
/* if we are in listemode enter in listenmain() else */
|
|
/* print HPING... bla bla bla and enter in wait_packet() */
|
|
if (opt_listenmode) {
|
|
fprintf(stderr, "hping3 listen mode\n");
|
|
|
|
/* memory protection */
|
|
if (memlockall() == -1) {
|
|
perror("[main] memlockall()");
|
|
fprintf(stderr, "Warning: can't disable memory paging!\n");
|
|
} else if (opt_verbose || opt_debug) {
|
|
printf("Memory paging disabled\n");
|
|
}
|
|
listenmain();
|
|
/* UNREACHED */
|
|
}
|
|
|
|
/* Scan mode */
|
|
if (opt_scanmode) {
|
|
fprintf(stderr, "Scanning %s (%s), port %s\n",
|
|
targetname, targetstraddr, opt_scanports);
|
|
scanmain();
|
|
/* UNREACHED */
|
|
}
|
|
|
|
if (opt_rawipmode) {
|
|
strcat(setflags, "raw IP mode");
|
|
hdr_size = IPHDR_SIZE;
|
|
} else if (opt_icmpmode) {
|
|
strcat(setflags, "icmp mode");
|
|
hdr_size = IPHDR_SIZE + ICMPHDR_SIZE;
|
|
} else if (opt_udpmode) {
|
|
strcat(setflags, "udp mode");
|
|
hdr_size = IPHDR_SIZE + UDPHDR_SIZE;
|
|
} else {
|
|
if (tcp_th_flags & TH_RST) strcat(setflags, "R");
|
|
if (tcp_th_flags & TH_SYN) strcat(setflags, "S");
|
|
if (tcp_th_flags & TH_ACK) strcat(setflags, "A");
|
|
if (tcp_th_flags & TH_FIN) strcat(setflags, "F");
|
|
if (tcp_th_flags & TH_PUSH) strcat(setflags, "P");
|
|
if (tcp_th_flags & TH_URG) strcat(setflags, "U");
|
|
if (tcp_th_flags & TH_X) strcat(setflags, "X");
|
|
if (tcp_th_flags & TH_Y) strcat(setflags, "Y");
|
|
if (setflags[0] == '\0') strcat(setflags, "NO FLAGS are");
|
|
hdr_size = IPHDR_SIZE + TCPHDR_SIZE;
|
|
}
|
|
|
|
if(opt_ipv6)
|
|
hdr_size += IP6HDR_SIZE - IPHDR_SIZE;
|
|
|
|
printf("HPING %s (%s %s): %s set, %d headers + %d data bytes\n",
|
|
targetname,
|
|
ifname,
|
|
targetstraddr,
|
|
setflags,
|
|
hdr_size,
|
|
data_size);
|
|
|
|
/* memory protection */
|
|
if (opt_datafromfile || opt_sign) {
|
|
if (memlockall() == -1) {
|
|
perror("[main] memlockall()");
|
|
fprintf(stderr,
|
|
"Warning: can't disable memory paging!\n");
|
|
} else if (opt_verbose || opt_debug) {
|
|
printf("Memory paging disabled\n");
|
|
}
|
|
}
|
|
|
|
/* start packet sending */
|
|
kill(getpid(), SIGALRM);
|
|
|
|
/* flood mode? */
|
|
if (opt_flood) {
|
|
fprintf(stderr,
|
|
"hping in flood mode, no replies will be shown\n");
|
|
while (1) {
|
|
send_packet(0);
|
|
}
|
|
}
|
|
|
|
/* main loop */
|
|
while(1)
|
|
wait_packet();
|
|
|
|
return 0;
|
|
}
|