masscan-mark-ii/src/proto-icmp.c

191 lines
6.3 KiB
C

#include "proto-icmp.h"
#include "proto-preprocess.h"
#include "syn-cookie.h"
#include "util-logger.h"
#include "output.h"
#include "masscan-status.h"
#include "massip-port.h"
#include "main-dedup.h"
/***************************************************************************
***************************************************************************/
static int
matches_me(struct Output *out, ipaddress ip, unsigned port)
{
unsigned i;
for (i=0; i<8; i++) {
if (is_myself(&out->src[i], ip, port))
return 1;
}
return 0;
}
/***************************************************************************
***************************************************************************/
static int
parse_port_unreachable(const unsigned char *px, unsigned length,
unsigned *r_ip_me, unsigned *r_ip_them,
unsigned *r_port_me, unsigned *r_port_them,
unsigned *r_ip_proto)
{
if (length < 24)
return -1;
*r_ip_me = px[12]<<24 | px[13]<<16 | px[14]<<8 | px[15];
*r_ip_them = px[16]<<24 | px[17]<<16 | px[18]<<8 | px[19];
*r_ip_proto = px[9]; /* TCP=6, UDP=17 */
px += (px[0]&0xF)<<2;
length -= (px[0]&0xF)<<2;
if (length < 4)
return -1;
*r_port_me = px[0]<<8 | px[1];
*r_port_them = px[2]<<8 | px[3];
return 0;
}
/***************************************************************************
* This is where we handle all incoming ICMP packets. Some of these packets
* will be due to scans we are doing, like pings (echoes). Some will
* be inadvertent, such as "destination unreachable" messages.
***************************************************************************/
void
handle_icmp(struct Output *out, time_t timestamp,
const unsigned char *px, unsigned length,
struct PreprocessedInfo *parsed,
uint64_t entropy)
{
unsigned type = parsed->port_src;
unsigned code = parsed->port_dst;
unsigned seqno_me;
ipaddress ip_me = parsed->dst_ip;
ipaddress ip_them = parsed->src_ip;
unsigned cookie;
/* dedup ICMP echo replies as well as SYN/ACK replies */
static struct DedupTable *echo_reply_dedup = NULL;
if (!echo_reply_dedup)
echo_reply_dedup = dedup_create();
seqno_me = px[parsed->transport_offset+4]<<24
| px[parsed->transport_offset+5]<<16
| px[parsed->transport_offset+6]<<8
| px[parsed->transport_offset+7]<<0;
switch (type) {
case 0: /* ICMP echo reply */
case 129:
cookie = (unsigned)syn_cookie(ip_them, Templ_ICMP_echo, ip_me, 0, entropy);
if ((cookie & 0xFFFFFFFF) != seqno_me)
return; /* not my response */
if (dedup_is_duplicate(echo_reply_dedup, ip_them, 0, ip_me, 0))
break;
//if (syn_hash(ip_them, Templ_ICMP_echo) != seqno_me)
// return; /* not my response */
/*
* Report "open" or "existence" of host
*/
output_report_status(
out,
timestamp,
PortStatus_Open,
ip_them,
1, /* ip proto */
0,
0,
parsed->ip_ttl,
parsed->mac_src);
break;
case 3: /* destination unreachable */
switch (code) {
case 0: /* net unreachable */
/* We get these a lot while port scanning, often a flood coming
* back from broken/misconfigured networks */
break;
case 1: /* host unreachable */
/* This means the router doesn't exist */
break;
case 2: /* protocol unreachable */
/* The host exists, but it doesn't support SCTP */
break;
case 3: /* port unreachable */
if (length - parsed->transport_offset > 8) {
ipaddress ip_me2;
ipaddress ip_them2;
unsigned port_me2, port_them2;
unsigned ip_proto;
int err;
ip_me2.version = 4;
ip_them2.version = 4;
err = parse_port_unreachable(
px + parsed->transport_offset + 8,
length - parsed->transport_offset + 8,
&ip_me2.ipv4, &ip_them2.ipv4, &port_me2, &port_them2,
&ip_proto);
if (err)
return;
if (!matches_me(out, ip_me2, port_me2))
return;
switch (ip_proto) {
case 6:
output_report_status(
out,
timestamp,
PortStatus_Closed,
ip_them2,
ip_proto,
port_them2,
0,
parsed->ip_ttl,
parsed->mac_src);
break;
case 17:
output_report_status(
out,
timestamp,
PortStatus_Closed,
ip_them2,
ip_proto,
port_them2,
0,
parsed->ip_ttl,
parsed->mac_src);
break;
case 132:
output_report_status(
out,
timestamp,
PortStatus_Closed,
ip_them2,
ip_proto,
port_them2,
0,
parsed->ip_ttl,
parsed->mac_src);
break;
}
}
}
break;
default:
;
}
}