#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: ; } }