mirror of
https://github.com/nmap/nmap.git
synced 2026-05-13 08:46:45 +00:00
Avoid undefined behavior from unaligned accesses
This commit is contained in:
parent
ab973f548a
commit
8ef3ed1471
8 changed files with 610 additions and 523 deletions
|
|
@ -548,7 +548,7 @@ int mac_cache_set(const struct sockaddr_storage *ss, u8 *mac){
|
|||
}
|
||||
|
||||
/* Standard BSD internet checksum routine. Uses libdnet helper functions. */
|
||||
unsigned short in_cksum(u16 *ptr,int nbytes) {
|
||||
unsigned short in_cksum(const u16 *ptr,int nbytes) {
|
||||
int sum;
|
||||
|
||||
sum = ip_cksum_add(ptr, nbytes, 0);
|
||||
|
|
@ -558,6 +558,9 @@ unsigned short in_cksum(u16 *ptr,int nbytes) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const void *ipv4_get_data(const struct ip *ip, const void *p, unsigned int *len);
|
||||
const void *ipv6_get_data(const struct ip6_hdr *ip6, const void *p, unsigned int *len, u8 *nxt);
|
||||
const void *ipv6_get_data_any(const struct ip6_hdr *ip6, const void *p, unsigned int *len, u8 *nxt);
|
||||
|
||||
/* Return true iff this Next Header type is an extension header we must skip to
|
||||
get to the upper-layer header. Types for which neither this function nor
|
||||
|
|
@ -601,7 +604,7 @@ static int ipv6_is_upperlayer(u8 type)
|
|||
/* upperlayer_only controls whether we require a known upper-layer protocol at
|
||||
the end of the chain, or return the last readable header even if it is not an
|
||||
upper-layer protocol (may even be another extension header). */
|
||||
static const void *ipv6_get_data_primitive(const struct ip6_hdr *ip6,
|
||||
static const void *ipv6_get_data_primitive(const struct ip6_hdr *ip6, const void *packet,
|
||||
unsigned int *len, u8 *nxt, bool upperlayer_only)
|
||||
{
|
||||
const unsigned char *p, *end;
|
||||
|
|
@ -609,7 +612,7 @@ static const void *ipv6_get_data_primitive(const struct ip6_hdr *ip6,
|
|||
if (*len < sizeof(*ip6))
|
||||
return NULL;
|
||||
|
||||
p = (unsigned char *) ip6;
|
||||
p = (unsigned char *) packet;
|
||||
end = p + *len;
|
||||
|
||||
*nxt = ip6->ip6_nxt;
|
||||
|
|
@ -630,10 +633,10 @@ static const void *ipv6_get_data_primitive(const struct ip6_hdr *ip6,
|
|||
|
||||
static const void *ip_get_data_primitive(const void *packet, unsigned int *len,
|
||||
struct abstract_ip_hdr *hdr, bool upperlayer_only) {
|
||||
const struct ip *ip;
|
||||
struct ip ip;
|
||||
|
||||
ip = (struct ip *) packet;
|
||||
if (*len >= 20 && ip->ip_v == 4) {
|
||||
memcpy(&ip, packet, sizeof(ip));
|
||||
if (*len >= 20 && ip.ip_v == 4) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
hdr->version = 4;
|
||||
|
|
@ -641,19 +644,20 @@ static const void *ip_get_data_primitive(const void *packet, unsigned int *len,
|
|||
sin = (struct sockaddr_in *) &hdr->src;
|
||||
memset(&hdr->src, 0, sizeof(hdr->src));
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = ip->ip_src.s_addr;
|
||||
sin->sin_addr.s_addr = ip.ip_src.s_addr;
|
||||
|
||||
sin = (struct sockaddr_in *) &hdr->dst;
|
||||
memset(&hdr->dst, 0, sizeof(hdr->dst));
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = ip->ip_dst.s_addr;
|
||||
sin->sin_addr.s_addr = ip.ip_dst.s_addr;
|
||||
|
||||
hdr->proto = ip->ip_p;
|
||||
hdr->ttl = ip->ip_ttl;
|
||||
hdr->ipid = ntohs(ip->ip_id);
|
||||
return ipv4_get_data(ip, len);
|
||||
} else if (*len >= 40 && ip->ip_v == 6) {
|
||||
const struct ip6_hdr *ip6 = (struct ip6_hdr *) ip;
|
||||
hdr->proto = ip.ip_p;
|
||||
hdr->ttl = ip.ip_ttl;
|
||||
hdr->ipid = ntohs(ip.ip_id);
|
||||
return ipv4_get_data(&ip, packet, len);
|
||||
} else if (*len >= 40 && ip.ip_v == 6) {
|
||||
struct ip6_hdr ip6;
|
||||
memcpy(&ip6, packet, sizeof(ip6));
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
hdr->version = 6;
|
||||
|
|
@ -661,16 +665,16 @@ static const void *ip_get_data_primitive(const void *packet, unsigned int *len,
|
|||
sin6 = (struct sockaddr_in6 *) &hdr->src;
|
||||
memset(&hdr->src, 0, sizeof(hdr->src));
|
||||
sin6->sin6_family = AF_INET6;
|
||||
memcpy(&sin6->sin6_addr, &ip6->ip6_src, IP6_ADDR_LEN);
|
||||
memcpy(&sin6->sin6_addr, &ip6.ip6_src, IP6_ADDR_LEN);
|
||||
|
||||
sin6 = (struct sockaddr_in6 *) &hdr->dst;
|
||||
memset(&hdr->dst, 0, sizeof(hdr->dst));
|
||||
sin6->sin6_family = AF_INET6;
|
||||
memcpy(&sin6->sin6_addr, &ip6->ip6_dst, IP6_ADDR_LEN);
|
||||
memcpy(&sin6->sin6_addr, &ip6.ip6_dst, IP6_ADDR_LEN);
|
||||
|
||||
hdr->ttl = ip6->ip6_hlim;
|
||||
hdr->ipid = ntohl(ip6->ip6_flow & IP6_FLOWLABEL_MASK);
|
||||
return ipv6_get_data_primitive(ip6, len, &hdr->proto, upperlayer_only);
|
||||
hdr->ttl = ip6.ip6_hlim;
|
||||
hdr->ipid = ntohl(ip6.ip6_flow & IP6_FLOWLABEL_MASK);
|
||||
return ipv6_get_data_primitive(&ip6, packet, len, &hdr->proto, upperlayer_only);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -694,7 +698,7 @@ const void *ip_get_data_any(const void *packet, unsigned int *len,
|
|||
}
|
||||
|
||||
/* Get the upper-layer protocol from an IPv4 packet. */
|
||||
const void *ipv4_get_data(const struct ip *ip, unsigned int *len)
|
||||
const void *ipv4_get_data(const struct ip *ip, const void *p, unsigned int *len)
|
||||
{
|
||||
unsigned int header_len;
|
||||
|
||||
|
|
@ -707,33 +711,56 @@ const void *ipv4_get_data(const struct ip *ip, unsigned int *len)
|
|||
return NULL;
|
||||
*len -= header_len;
|
||||
|
||||
return (char *) ip + header_len;
|
||||
return (const u8 *)p + header_len;
|
||||
}
|
||||
|
||||
const void *ipv4_get_data(const void *p, unsigned int *len)
|
||||
{
|
||||
struct ip ip;
|
||||
memcpy(&ip, p, sizeof(ip));
|
||||
return ipv4_get_data(&ip, p, len);
|
||||
}
|
||||
|
||||
/* Get the upper-layer protocol from an IPv6 packet. This skips over known
|
||||
extension headers. The length of the upper-layer payload is stored in *len.
|
||||
The protocol is stored in *nxt. Returns NULL in case of error. */
|
||||
const void *ipv6_get_data(const struct ip6_hdr *ip6, unsigned int *len, u8 *nxt)
|
||||
const void *ipv6_get_data(const struct ip6_hdr *ip6, const void *p, unsigned int *len, u8 *nxt)
|
||||
{
|
||||
return ipv6_get_data_primitive(ip6, len, nxt, true);
|
||||
return ipv6_get_data_primitive(ip6, p, len, nxt, true);
|
||||
}
|
||||
|
||||
const void *ipv6_get_data(const void *p, unsigned int *len, u8 *nxt)
|
||||
{
|
||||
struct ip6_hdr ip6;
|
||||
memcpy(&ip6, p, sizeof(ip6));
|
||||
return ipv6_get_data(&ip6, p, len, nxt);
|
||||
}
|
||||
|
||||
/* Get the protocol payload from an IPv6 packet. This skips over known extension
|
||||
headers. It differs from ipv6_get_data in that it will return a result even
|
||||
if the final header is not a known upper-layer protocol. */
|
||||
const void *ipv6_get_data_any(const struct ip6_hdr *ip6, unsigned int *len, u8 *nxt)
|
||||
const void *ipv6_get_data_any(const struct ip6_hdr *ip6, const void *p, unsigned int *len, u8 *nxt)
|
||||
{
|
||||
return ipv6_get_data_primitive(ip6, len, nxt, false);
|
||||
return ipv6_get_data_primitive(ip6, p, len, nxt, false);
|
||||
}
|
||||
|
||||
const void *icmp_get_data(const struct icmp_hdr *icmp, unsigned int *len)
|
||||
const void *ipv6_get_data_any(const void *p, unsigned int *len, u8 *nxt)
|
||||
{
|
||||
struct ip6_hdr ip6;
|
||||
memcpy(&ip6, p, sizeof(ip6));
|
||||
return ipv6_get_data_any(&ip6, p, len, nxt);
|
||||
}
|
||||
|
||||
const void *icmp_get_data(const void *icmp, unsigned int *len)
|
||||
{
|
||||
unsigned int header_len;
|
||||
struct icmp_hdr hdr;
|
||||
memcpy(&hdr, icmp, sizeof(hdr));
|
||||
|
||||
if (icmp->icmp_type == ICMP_TIMEXCEED || icmp->icmp_type == ICMP_UNREACH)
|
||||
if (hdr.icmp_type == ICMP_TIMEXCEED || hdr.icmp_type == ICMP_UNREACH)
|
||||
header_len = 8;
|
||||
else
|
||||
netutil_fatal("%s passed ICMP packet with unhandled type %d", __func__, icmp->icmp_type);
|
||||
netutil_fatal("%s passed ICMP packet with unhandled type %d", __func__, hdr.icmp_type);
|
||||
if (header_len > *len)
|
||||
return NULL;
|
||||
*len -= header_len;
|
||||
|
|
@ -741,14 +768,16 @@ const void *icmp_get_data(const struct icmp_hdr *icmp, unsigned int *len)
|
|||
return (char *) icmp + header_len;
|
||||
}
|
||||
|
||||
const void *icmpv6_get_data(const struct icmpv6_hdr *icmpv6, unsigned int *len)
|
||||
const void *icmpv6_get_data(const void *icmpv6, unsigned int *len)
|
||||
{
|
||||
unsigned int header_len;
|
||||
struct icmpv6_hdr hdr;
|
||||
memcpy(&hdr, icmpv6, sizeof(hdr));
|
||||
|
||||
if (icmpv6->icmpv6_type == ICMPV6_TIMEXCEED || icmpv6->icmpv6_type == ICMPV6_UNREACH)
|
||||
if (hdr.icmpv6_type == ICMPV6_TIMEXCEED || hdr.icmpv6_type == ICMPV6_UNREACH)
|
||||
header_len = 8;
|
||||
else
|
||||
netutil_fatal("%s passed ICMPv6 packet with unhandled type %d", __func__, icmpv6->icmpv6_type);
|
||||
netutil_fatal("%s passed ICMPv6 packet with unhandled type %d", __func__, hdr.icmpv6_type);
|
||||
if (header_len > *len)
|
||||
return NULL;
|
||||
*len -= header_len;
|
||||
|
|
@ -2352,7 +2381,6 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
const u8 *data;
|
||||
unsigned int datalen;
|
||||
|
||||
struct tcp_hdr *tcp = NULL; /* TCP header structure. */
|
||||
struct udp_hdr *udp = NULL; /* UDP header structure. */
|
||||
struct sctp_hdr *sctp = NULL; /* SCTP header structure. */
|
||||
static char protoinfo[1024] = ""; /* Stores final info string. */
|
||||
|
|
@ -2381,11 +2409,10 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
|
||||
/* IP INFORMATION ************************************************************/
|
||||
if (hdr.version == 4) { /* IPv4 */
|
||||
const struct ip *ip;
|
||||
struct ip ip;
|
||||
memcpy(&ip, packet, sizeof(ip));
|
||||
const struct sockaddr_in *sin;
|
||||
|
||||
ip = (struct ip *) packet;
|
||||
|
||||
/* Obtain IP source and destination info */
|
||||
sin = (struct sockaddr_in *) &hdr.src;
|
||||
inet_ntop(AF_INET, (void *)&sin->sin_addr.s_addr, srchost, sizeof(srchost));
|
||||
|
|
@ -2393,10 +2420,10 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
inet_ntop(AF_INET, (void *)&sin->sin_addr.s_addr, dsthost, sizeof(dsthost));
|
||||
|
||||
/* Compute fragment offset and check if flags are set */
|
||||
frag_off = 8 * (ntohs(ip->ip_off) & 8191) /* 2^13 - 1 */;
|
||||
more_fragments = ntohs(ip->ip_off) & IP_MF;
|
||||
dont_fragment = ntohs(ip->ip_off) & IP_DF;
|
||||
reserved_flag = ntohs(ip->ip_off) & IP_RF;
|
||||
frag_off = 8 * (ntohs(ip.ip_off) & 8191) /* 2^13 - 1 */;
|
||||
more_fragments = ntohs(ip.ip_off) & IP_MF;
|
||||
dont_fragment = ntohs(ip.ip_off) & IP_DF;
|
||||
reserved_flag = ntohs(ip.ip_off) & IP_RF;
|
||||
|
||||
/* Is this a fragmented packet? is it the last fragment? */
|
||||
if (frag_off || more_fragments) {
|
||||
|
|
@ -2406,33 +2433,33 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
/* Create a string with information relevant to the specified level of detail */
|
||||
if (detail == LOW_DETAIL) {
|
||||
Snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%hu iplen=%hu%s %s%s%s",
|
||||
ip->ip_ttl, (unsigned short) ntohs(ip->ip_id), (unsigned short) ntohs(ip->ip_len), fragnfo,
|
||||
ip->ip_hl==5?"":"ipopts={",
|
||||
ip->ip_hl==5?"":format_ip_options((u8*) ip + sizeof(struct ip), MIN((unsigned)(ip->ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip->ip_hl==5?"":"}");
|
||||
ip.ip_ttl, (unsigned short) ntohs(ip.ip_id), (unsigned short) ntohs(ip.ip_len), fragnfo,
|
||||
ip.ip_hl==5?"":"ipopts={",
|
||||
ip.ip_hl==5?"":format_ip_options((u8*) packet + sizeof(struct ip), MIN((unsigned)(ip.ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip.ip_hl==5?"":"}");
|
||||
} else if (detail == MEDIUM_DETAIL) {
|
||||
Snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%hu proto=%d csum=0x%04x iplen=%hu%s %s%s%s",
|
||||
ip->ip_ttl, (unsigned short) ntohs(ip->ip_id),
|
||||
ip->ip_p, ntohs(ip->ip_sum),
|
||||
(unsigned short) ntohs(ip->ip_len), fragnfo,
|
||||
ip->ip_hl==5?"":"ipopts={",
|
||||
ip->ip_hl==5?"":format_ip_options((u8*) ip + sizeof(struct ip), MIN((unsigned)(ip->ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip->ip_hl==5?"":"}");
|
||||
ip.ip_ttl, (unsigned short) ntohs(ip.ip_id),
|
||||
ip.ip_p, ntohs(ip.ip_sum),
|
||||
(unsigned short) ntohs(ip.ip_len), fragnfo,
|
||||
ip.ip_hl==5?"":"ipopts={",
|
||||
ip.ip_hl==5?"":format_ip_options((u8*) packet + sizeof(struct ip), MIN((unsigned)(ip.ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip.ip_hl==5?"":"}");
|
||||
} else if (detail == HIGH_DETAIL) {
|
||||
Snprintf(ipinfo, sizeof(ipinfo), "ver=%d ihl=%d tos=0x%02x iplen=%hu id=%hu%s%s%s%s foff=%d%s ttl=%d proto=%d csum=0x%04x%s%s%s",
|
||||
ip->ip_v, ip->ip_hl,
|
||||
ip->ip_tos, (unsigned short) ntohs(ip->ip_len),
|
||||
(unsigned short) ntohs(ip->ip_id),
|
||||
ip.ip_v, ip.ip_hl,
|
||||
ip.ip_tos, (unsigned short) ntohs(ip.ip_len),
|
||||
(unsigned short) ntohs(ip.ip_id),
|
||||
(reserved_flag||dont_fragment||more_fragments) ? " flg=" : "",
|
||||
(reserved_flag)? "x" : "",
|
||||
(dont_fragment)? "D" : "",
|
||||
(more_fragments)? "M": "",
|
||||
frag_off, (more_fragments) ? "+" : "",
|
||||
ip->ip_ttl, ip->ip_p,
|
||||
ntohs(ip->ip_sum),
|
||||
ip->ip_hl==5?"":" ipopts={",
|
||||
ip->ip_hl==5?"":format_ip_options((u8*) ip + sizeof(struct ip), MIN((unsigned)(ip->ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip->ip_hl==5?"":"}");
|
||||
ip.ip_ttl, ip.ip_p,
|
||||
ntohs(ip.ip_sum),
|
||||
ip.ip_hl==5?"":" ipopts={",
|
||||
ip.ip_hl==5?"":format_ip_options((u8*) packet + sizeof(struct ip), MIN((unsigned)(ip.ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip.ip_hl==5?"":"}");
|
||||
}
|
||||
} else { /* IPv6 */
|
||||
const struct ip6_hdr *ip6;
|
||||
|
|
@ -2472,7 +2499,7 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
char tcpinfo[64] = "";
|
||||
char buf[32];
|
||||
char tcpoptinfo[256] = "";
|
||||
tcp = (struct tcp_hdr *) data;
|
||||
struct tcp_hdr tcp;
|
||||
|
||||
/* Let's parse the TCP header. The following code is very ugly because we
|
||||
* have to deal with a lot of different situations. We don't want to
|
||||
|
|
@ -2511,39 +2538,39 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
else if (frag_off > 0) {
|
||||
/* Fragmentation is on 8-byte boundaries, so 8 is the only legal value here. */
|
||||
assert(frag_off == 8);
|
||||
tcp = (struct tcp_hdr *)((u8 *) tcp - frag_off); // ugly?
|
||||
memcpy((u8 *)&tcp + frag_off, data - frag_off, sizeof(tcp) - frag_off);
|
||||
|
||||
/* TCP Flags */
|
||||
p = tflags;
|
||||
/* These are basically in tcpdump order */
|
||||
if (tcp->th_flags & TH_SYN)
|
||||
if (tcp.th_flags & TH_SYN)
|
||||
*p++ = 'S';
|
||||
if (tcp->th_flags & TH_FIN)
|
||||
if (tcp.th_flags & TH_FIN)
|
||||
*p++ = 'F';
|
||||
if (tcp->th_flags & TH_RST)
|
||||
if (tcp.th_flags & TH_RST)
|
||||
*p++ = 'R';
|
||||
if (tcp->th_flags & TH_PUSH)
|
||||
if (tcp.th_flags & TH_PUSH)
|
||||
*p++ = 'P';
|
||||
if (tcp->th_flags & TH_ACK) {
|
||||
if (tcp.th_flags & TH_ACK) {
|
||||
*p++ = 'A';
|
||||
Snprintf(tcpinfo, sizeof(tcpinfo), " ack=%lu",
|
||||
(unsigned long) ntohl(tcp->th_ack));
|
||||
(unsigned long) ntohl(tcp.th_ack));
|
||||
}
|
||||
if (tcp->th_flags & TH_URG)
|
||||
if (tcp.th_flags & TH_URG)
|
||||
*p++ = 'U';
|
||||
if (tcp->th_flags & TH_ECE)
|
||||
if (tcp.th_flags & TH_ECE)
|
||||
*p++ = 'E'; /* rfc 2481/3168 */
|
||||
if (tcp->th_flags & TH_CWR)
|
||||
if (tcp.th_flags & TH_CWR)
|
||||
*p++ = 'C'; /* rfc 2481/3168 */
|
||||
*p++ = '\0';
|
||||
|
||||
/* TCP Options */
|
||||
if ((u32) tcp->th_off * 4 > sizeof(struct tcp_hdr)) {
|
||||
if (datalen < (u32) tcp->th_off * 4 - frag_off) {
|
||||
if ((u32) tcp.th_off * 4 > sizeof(struct tcp_hdr)) {
|
||||
if (datalen < (u32) tcp.th_off * 4 - frag_off) {
|
||||
Snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete");
|
||||
} else {
|
||||
tcppacketoptinfo((u8*) tcp + sizeof(struct tcp_hdr),
|
||||
tcp->th_off*4 - sizeof(struct tcp_hdr),
|
||||
tcppacketoptinfo((u8*) data + sizeof(struct tcp_hdr),
|
||||
tcp.th_off*4 - sizeof(struct tcp_hdr),
|
||||
tcpoptinfo, sizeof(tcpoptinfo));
|
||||
}
|
||||
}
|
||||
|
|
@ -2554,22 +2581,22 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
} else if (detail == MEDIUM_DETAIL) {
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? %s ack=%lu win=%hu %s IP [%s]",
|
||||
srchost, dsthost, tflags,
|
||||
(unsigned long) ntohl(tcp->th_ack), (unsigned short) ntohs(tcp->th_win),
|
||||
(unsigned long) ntohl(tcp.th_ack), (unsigned short) ntohs(tcp.th_win),
|
||||
tcpoptinfo, ipinfo);
|
||||
} else if (detail == HIGH_DETAIL) {
|
||||
if (datalen >= 12) { /* We have at least bytes 8-20 */
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:?? > %s:?? %s seq=%lu ack=%lu off=%d res=%d win=%hu csum=0x%04X urp=%hu%s%s] IP [%s]",
|
||||
srchost, dsthost, tflags,
|
||||
(unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned long) ntohl(tcp->th_ack),
|
||||
(u8)tcp->th_off, (u8)tcp->th_x2, (unsigned short) ntohs(tcp->th_win),
|
||||
ntohs(tcp->th_sum), (unsigned short) ntohs(tcp->th_urp),
|
||||
(unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned long) ntohl(tcp.th_ack),
|
||||
(u8)tcp.th_off, (u8)tcp.th_x2, (unsigned short) ntohs(tcp.th_win),
|
||||
ntohs(tcp.th_sum), (unsigned short) ntohs(tcp.th_urp),
|
||||
(tcpoptinfo[0]!='\0') ? " " : "",
|
||||
tcpoptinfo, ipinfo);
|
||||
} else { /* We only have bytes 8-16 */
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? %s ack=%lu win=%hu %s IP [%s]",
|
||||
srchost, dsthost, tflags,
|
||||
(unsigned long) ntohl(tcp->th_ack), (unsigned short) ntohs(tcp->th_win),
|
||||
(unsigned long) ntohl(tcp.th_ack), (unsigned short) ntohs(tcp.th_win),
|
||||
tcpoptinfo, ipinfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -2579,25 +2606,26 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
/* CASE 3: where the IP packet is not a fragment but for some reason, we
|
||||
* don't have the entire TCP header, just part of it.*/
|
||||
else if (datalen < 20) {
|
||||
memcpy(&tcp, data, MIN(datalen, sizeof(tcp)));
|
||||
/* We know we have the first 8 bytes, so what's left? */
|
||||
/* We only have the first 64 bits: ports and seq number */
|
||||
if (datalen < 12) {
|
||||
Snprintf(tcpinfo, sizeof(tcpinfo), "TCP %s:%hu > %s:%hu ?? seq=%lu (incomplete) %s",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost,
|
||||
(unsigned short) ntohs(tcp->th_dport), (unsigned long) ntohl(tcp->th_seq), ipinfo);
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost,
|
||||
(unsigned short) ntohs(tcp.th_dport), (unsigned long) ntohl(tcp.th_seq), ipinfo);
|
||||
}
|
||||
|
||||
/* We only have the first 96 bits: ports, seq and ack number */
|
||||
else if (datalen < 16) {
|
||||
if (detail == LOW_DETAIL) { /* We don't print ACK in low detail */
|
||||
Snprintf(tcpinfo, sizeof(tcpinfo), "TCP %s:%hu > %s:%hu seq=%lu (incomplete), %s",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost,
|
||||
(unsigned short) ntohs(tcp->th_dport), (unsigned long) ntohl(tcp->th_seq), ipinfo);
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost,
|
||||
(unsigned short) ntohs(tcp.th_dport), (unsigned long) ntohl(tcp.th_seq), ipinfo);
|
||||
} else {
|
||||
Snprintf(tcpinfo, sizeof(tcpinfo), "TCP [%s:%hu > %s:%hu seq=%lu ack=%lu (incomplete)] IP [%s]",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost,
|
||||
(unsigned short) ntohs(tcp->th_dport), (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned long) ntohl(tcp->th_ack), ipinfo);
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost,
|
||||
(unsigned short) ntohs(tcp.th_dport), (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned long) ntohl(tcp.th_ack), ipinfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2605,25 +2633,25 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
else {
|
||||
p = tflags;
|
||||
/* These are basically in tcpdump order */
|
||||
if (tcp->th_flags & TH_SYN)
|
||||
if (tcp.th_flags & TH_SYN)
|
||||
*p++ = 'S';
|
||||
if (tcp->th_flags & TH_FIN)
|
||||
if (tcp.th_flags & TH_FIN)
|
||||
*p++ = 'F';
|
||||
if (tcp->th_flags & TH_RST)
|
||||
if (tcp.th_flags & TH_RST)
|
||||
*p++ = 'R';
|
||||
if (tcp->th_flags & TH_PUSH)
|
||||
if (tcp.th_flags & TH_PUSH)
|
||||
*p++ = 'P';
|
||||
if (tcp->th_flags & TH_ACK) {
|
||||
if (tcp.th_flags & TH_ACK) {
|
||||
*p++ = 'A';
|
||||
Snprintf(buf, sizeof(buf), " ack=%lu",
|
||||
(unsigned long) ntohl(tcp->th_ack));
|
||||
(unsigned long) ntohl(tcp.th_ack));
|
||||
strncat(tcpinfo, buf, sizeof(tcpinfo) - strlen(tcpinfo) - 1);
|
||||
}
|
||||
if (tcp->th_flags & TH_URG)
|
||||
if (tcp.th_flags & TH_URG)
|
||||
*p++ = 'U';
|
||||
if (tcp->th_flags & TH_ECE)
|
||||
if (tcp.th_flags & TH_ECE)
|
||||
*p++ = 'E'; /* rfc 2481/3168 */
|
||||
if (tcp->th_flags & TH_CWR)
|
||||
if (tcp.th_flags & TH_CWR)
|
||||
*p++ = 'C'; /* rfc 2481/3168 */
|
||||
*p++ = '\0';
|
||||
|
||||
|
|
@ -2631,22 +2659,22 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
/* Create a string with TCP information relevant to the specified level of detail */
|
||||
if (detail == LOW_DETAIL) { /* We don't print ACK in low detail */
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%hu > %s:%hu %s %s seq=%lu win=%hu (incomplete)",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost, (unsigned short) ntohs(tcp->th_dport),
|
||||
tflags, ipinfo, (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned short) ntohs(tcp->th_win));
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost, (unsigned short) ntohs(tcp.th_dport),
|
||||
tflags, ipinfo, (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned short) ntohs(tcp.th_win));
|
||||
} else if (detail == MEDIUM_DETAIL) {
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:%hu > %s:%hu %s seq=%lu ack=%lu win=%hu (incomplete)] IP [%s]",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost, (unsigned short) ntohs(tcp->th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned long) ntohl(tcp->th_ack),
|
||||
(unsigned short) ntohs(tcp->th_win), ipinfo);
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost, (unsigned short) ntohs(tcp.th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned long) ntohl(tcp.th_ack),
|
||||
(unsigned short) ntohs(tcp.th_win), ipinfo);
|
||||
} else if (detail == HIGH_DETAIL) {
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:%hu > %s:%hu %s seq=%lu ack=%lu off=%d res=%d win=%hu (incomplete)] IP [%s]",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport),
|
||||
dsthost, (unsigned short) ntohs(tcp->th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned long) ntohl(tcp->th_ack),
|
||||
(u8)tcp->th_off, (u8)tcp->th_x2, (unsigned short) ntohs(tcp->th_win),
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport),
|
||||
dsthost, (unsigned short) ntohs(tcp.th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned long) ntohl(tcp.th_ack),
|
||||
(u8)tcp.th_off, (u8)tcp.th_x2, (unsigned short) ntohs(tcp.th_win),
|
||||
ipinfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -2655,39 +2683,40 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
/* CASE 4: where we (finally!) have a full 20 byte TCP header so we can
|
||||
* safely print all fields */
|
||||
else { /* if (datalen >= 20) */
|
||||
memcpy(&tcp, data, MIN(datalen, sizeof(tcp)));
|
||||
|
||||
/* TCP Flags */
|
||||
p = tflags;
|
||||
/* These are basically in tcpdump order */
|
||||
if (tcp->th_flags & TH_SYN)
|
||||
if (tcp.th_flags & TH_SYN)
|
||||
*p++ = 'S';
|
||||
if (tcp->th_flags & TH_FIN)
|
||||
if (tcp.th_flags & TH_FIN)
|
||||
*p++ = 'F';
|
||||
if (tcp->th_flags & TH_RST)
|
||||
if (tcp.th_flags & TH_RST)
|
||||
*p++ = 'R';
|
||||
if (tcp->th_flags & TH_PUSH)
|
||||
if (tcp.th_flags & TH_PUSH)
|
||||
*p++ = 'P';
|
||||
if (tcp->th_flags & TH_ACK) {
|
||||
if (tcp.th_flags & TH_ACK) {
|
||||
*p++ = 'A';
|
||||
Snprintf(buf, sizeof(buf), " ack=%lu",
|
||||
(unsigned long) ntohl(tcp->th_ack));
|
||||
(unsigned long) ntohl(tcp.th_ack));
|
||||
strncat(tcpinfo, buf, sizeof(tcpinfo) - strlen(tcpinfo) - 1);
|
||||
}
|
||||
if (tcp->th_flags & TH_URG)
|
||||
if (tcp.th_flags & TH_URG)
|
||||
*p++ = 'U';
|
||||
if (tcp->th_flags & TH_ECE)
|
||||
if (tcp.th_flags & TH_ECE)
|
||||
*p++ = 'E'; /* rfc 2481/3168 */
|
||||
if (tcp->th_flags & TH_CWR)
|
||||
if (tcp.th_flags & TH_CWR)
|
||||
*p++ = 'C'; /* rfc 2481/3168 */
|
||||
*p++ = '\0';
|
||||
|
||||
/* TCP Options */
|
||||
if ((u32) tcp->th_off * 4 > sizeof(struct tcp_hdr)) {
|
||||
if (datalen < (unsigned int) tcp->th_off * 4) {
|
||||
if ((u32) tcp.th_off * 4 > sizeof(struct tcp_hdr)) {
|
||||
if (datalen < (unsigned int) tcp.th_off * 4) {
|
||||
Snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete");
|
||||
} else {
|
||||
tcppacketoptinfo((u8*) tcp + sizeof(struct tcp_hdr),
|
||||
tcp->th_off*4 - sizeof(struct tcp_hdr),
|
||||
tcppacketoptinfo((u8*) data + sizeof(struct tcp_hdr),
|
||||
tcp.th_off*4 - sizeof(struct tcp_hdr),
|
||||
tcpoptinfo, sizeof(tcpoptinfo));
|
||||
}
|
||||
}
|
||||
|
|
@ -2695,24 +2724,24 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
/* Rest of header fields */
|
||||
if (detail == LOW_DETAIL) {
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%hu > %s:%hu %s %s seq=%lu win=%hu %s",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost, (unsigned short) ntohs(tcp->th_dport),
|
||||
tflags, ipinfo, (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned short) ntohs(tcp->th_win), tcpoptinfo);
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost, (unsigned short) ntohs(tcp.th_dport),
|
||||
tflags, ipinfo, (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned short) ntohs(tcp.th_win), tcpoptinfo);
|
||||
} else if (detail == MEDIUM_DETAIL) {
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:%hu > %s:%hu %s seq=%lu win=%hu csum=0x%04X%s%s] IP [%s]",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport), dsthost, (unsigned short) ntohs(tcp->th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned short) ntohs(tcp->th_win), (unsigned short) ntohs(tcp->th_sum),
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport), dsthost, (unsigned short) ntohs(tcp.th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned short) ntohs(tcp.th_win), (unsigned short) ntohs(tcp.th_sum),
|
||||
(tcpoptinfo[0]!='\0') ? " " : "",
|
||||
tcpoptinfo, ipinfo);
|
||||
} else if (detail == HIGH_DETAIL) {
|
||||
Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:%hu > %s:%hu %s seq=%lu ack=%lu off=%d res=%d win=%hu csum=0x%04X urp=%hu%s%s] IP [%s]",
|
||||
srchost, (unsigned short) ntohs(tcp->th_sport),
|
||||
dsthost, (unsigned short) ntohs(tcp->th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp->th_seq),
|
||||
(unsigned long) ntohl(tcp->th_ack),
|
||||
(u8)tcp->th_off, (u8)tcp->th_x2, (unsigned short) ntohs(tcp->th_win),
|
||||
ntohs(tcp->th_sum), (unsigned short) ntohs(tcp->th_urp),
|
||||
srchost, (unsigned short) ntohs(tcp.th_sport),
|
||||
dsthost, (unsigned short) ntohs(tcp.th_dport),
|
||||
tflags, (unsigned long) ntohl(tcp.th_seq),
|
||||
(unsigned long) ntohl(tcp.th_ack),
|
||||
(u8)tcp.th_off, (u8)tcp.th_x2, (unsigned short) ntohs(tcp.th_win),
|
||||
ntohs(tcp.th_sum), (unsigned short) ntohs(tcp.th_urp),
|
||||
(tcpoptinfo[0]!='\0') ? " " : "",
|
||||
tcpoptinfo, ipinfo);
|
||||
}
|
||||
|
|
@ -2868,14 +2897,6 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
if ((ip2->ip_v != 4) || ((ip2->ip_hl * 4) < 20) || ((ip2->ip_hl * 4) > 60)) {
|
||||
Snprintf(icmptype, sizeof icmptype, "Destination unreachable (bogus original datagram)");
|
||||
goto icmpbad;
|
||||
} else {
|
||||
/* We have the original datagram + the first 8 bytes of the
|
||||
* transport layer header */
|
||||
if (pktlen + 8 < datalen) {
|
||||
tcp = (struct tcp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4));
|
||||
udp = (struct udp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4));
|
||||
sctp = (struct sctp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4));
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the IP the original datagram was sent to */
|
||||
|
|
@ -2897,12 +2918,21 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
|
|||
|
||||
case 3:
|
||||
if (pktlen + 8 < datalen) {
|
||||
if (ip2->ip_p == IPPROTO_UDP && udp)
|
||||
Snprintf(icmptype, sizeof icmptype, "Port %hu unreachable", (unsigned short) ntohs(udp->uh_dport));
|
||||
else if (ip2->ip_p == IPPROTO_TCP && tcp)
|
||||
Snprintf(icmptype, sizeof icmptype, "Port %hu unreachable", (unsigned short) ntohs(tcp->th_dport));
|
||||
else if (ip2->ip_p == IPPROTO_SCTP && sctp)
|
||||
Snprintf(icmptype, sizeof icmptype, "Port %hu unreachable", (unsigned short) ntohs(sctp->sh_dport));
|
||||
/* We have the original datagram + the first 8 bytes of the
|
||||
* transport layer header */
|
||||
const u8 *pp = (const u8 *)ip2 + (ip2->ip_hl * 4);
|
||||
int offset = -1;
|
||||
if (ip2->ip_p == IPPROTO_UDP)
|
||||
offset = offsetof(struct udp_hdr, uh_dport);
|
||||
else if (ip2->ip_p == IPPROTO_TCP)
|
||||
offset = offsetof(struct tcp_hdr, th_dport);
|
||||
else if (ip2->ip_p == IPPROTO_SCTP)
|
||||
offset = offsetof(struct sctp_hdr, sh_dport);
|
||||
|
||||
if (offset >= 0) {
|
||||
pp += offset;
|
||||
Snprintf(icmptype, sizeof icmptype, "Port %hu unreachable", (u16)((pp[0] << 8) + pp[1]));
|
||||
}
|
||||
else
|
||||
Snprintf(icmptype, sizeof icmptype, "Port unreachable (unknown protocol %u)", ip2->ip_p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,17 +184,17 @@ const void *ip_get_data(const void *packet, unsigned int *len,
|
|||
const void *ip_get_data_any(const void *packet, unsigned int *len,
|
||||
struct abstract_ip_hdr *hdr);
|
||||
/* Get the upper-layer protocol from an IPv4 packet. */
|
||||
const void *ipv4_get_data(const struct ip *ip, unsigned int *len);
|
||||
const void *ipv4_get_data(const void *ip, unsigned int *len);
|
||||
/* Get the upper-layer protocol from an IPv6 packet. This skips over known
|
||||
extension headers. The length of the upper-layer payload is stored in *len.
|
||||
The protocol is stored in *nxt. Returns NULL in case of error. */
|
||||
const void *ipv6_get_data(const struct ip6_hdr *ip6, unsigned int *len, u8 *nxt);
|
||||
const void *ipv6_get_data_any(const struct ip6_hdr *ip6, unsigned int *len, u8 *nxt);
|
||||
const void *icmp_get_data(const struct icmp_hdr *icmp, unsigned int *len);
|
||||
const void *icmpv6_get_data(const struct icmpv6_hdr *icmpv6, unsigned int *len);
|
||||
const void *ipv6_get_data(const void *ip6, unsigned int *len, u8 *nxt);
|
||||
const void *ipv6_get_data_any(const void *ip6, unsigned int *len, u8 *nxt);
|
||||
const void *icmp_get_data(const void *icmp, unsigned int *len);
|
||||
const void *icmpv6_get_data(const void *icmpv6, unsigned int *len);
|
||||
|
||||
/* Standard BSD internet checksum routine. */
|
||||
unsigned short in_cksum(u16 *ptr, int nbytes);
|
||||
unsigned short in_cksum(const u16 *ptr, int nbytes);
|
||||
|
||||
/* Calculate the Internet checksum of some given data concatentated with the
|
||||
IPv4 pseudo-header. See RFC 1071 and TCP/IP Illustrated sections 3.2, 11.3,
|
||||
|
|
|
|||
312
osscan2.cc
312
osscan2.cc
|
|
@ -463,7 +463,6 @@ static void doSeqTests(OsScanInfo *OSI, HostOsScan *HOS) {
|
|||
unsigned int expectReplies = 0;
|
||||
long to_usec = 0;
|
||||
int timeToSleep = 0;
|
||||
struct ip *ip = NULL;
|
||||
struct link_header linkhdr;
|
||||
struct sockaddr_storage ss;
|
||||
unsigned int bytes = 0;
|
||||
|
|
@ -560,7 +559,7 @@ static void doSeqTests(OsScanInfo *OSI, HostOsScan *HOS) {
|
|||
if (o.debugging > 2)
|
||||
log_write(LOG_PLAIN, "pcap wait time is %ld.\n", to_usec);
|
||||
|
||||
ip = (struct ip*) readipv4_pcap(HOS->pd, &bytes, to_usec, &rcvdtime, &linkhdr, true);
|
||||
const u8 *ip = readipv4_pcap(HOS->pd, &bytes, to_usec, &rcvdtime, &linkhdr, true);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
|
|
@ -577,11 +576,15 @@ static void doSeqTests(OsScanInfo *OSI, HostOsScan *HOS) {
|
|||
timedout = true;
|
||||
}
|
||||
|
||||
if (bytes < (4 * ip->ip_hl) + 4U)
|
||||
struct ip iphdr;
|
||||
if (bytes < sizeof(iphdr))
|
||||
continue;
|
||||
memcpy(&iphdr, ip, sizeof(iphdr));
|
||||
if (bytes < (4 * iphdr.ip_hl) + 4U)
|
||||
continue;
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
((struct sockaddr_in *) &ss)->sin_addr.s_addr = ip->ip_src.s_addr;
|
||||
((struct sockaddr_in *) &ss)->sin_addr.s_addr = iphdr.ip_src.s_addr;
|
||||
ss.ss_family = AF_INET;
|
||||
hsi = OSI->findIncompleteHost(&ss);
|
||||
if (!hsi)
|
||||
|
|
@ -630,7 +633,6 @@ static void doTUITests(OsScanInfo *OSI, HostOsScan *HOS) {
|
|||
long to_usec;
|
||||
int timeToSleep = 0;
|
||||
|
||||
struct ip *ip = NULL;
|
||||
struct link_header linkhdr;
|
||||
struct sockaddr_storage ss;
|
||||
unsigned int bytes;
|
||||
|
|
@ -731,7 +733,7 @@ static void doTUITests(OsScanInfo *OSI, HostOsScan *HOS) {
|
|||
if (o.debugging > 2)
|
||||
log_write(LOG_PLAIN, "pcap wait time is %ld.\n", to_usec);
|
||||
|
||||
ip = (struct ip*) readipv4_pcap(HOS->pd, &bytes, to_usec, &rcvdtime, &linkhdr, true);
|
||||
const u8 *ip = readipv4_pcap(HOS->pd, &bytes, to_usec, &rcvdtime, &linkhdr, true);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
|
|
@ -748,11 +750,15 @@ static void doTUITests(OsScanInfo *OSI, HostOsScan *HOS) {
|
|||
timedout = true;
|
||||
}
|
||||
|
||||
if (bytes < (4 * ip->ip_hl) + 4U)
|
||||
struct ip iphdr;
|
||||
if (bytes < sizeof(iphdr))
|
||||
continue;
|
||||
memcpy(&iphdr, ip, sizeof(iphdr));
|
||||
if (bytes < (4 * iphdr.ip_hl) + 4U)
|
||||
continue;
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
((struct sockaddr_in *) &ss)->sin_addr.s_addr = ip->ip_src.s_addr;
|
||||
((struct sockaddr_in *) &ss)->sin_addr.s_addr = iphdr.ip_src.s_addr;
|
||||
ss.ss_family = AF_INET;
|
||||
hsi = OSI->findIncompleteHost(&ss);
|
||||
if (!hsi)
|
||||
|
|
@ -1889,36 +1895,39 @@ void HostOsScan::sendTUdpProbe(HostOsScanStats *hss, int probeNo) {
|
|||
}
|
||||
|
||||
|
||||
bool HostOsScan::processResp(HostOsScanStats *hss, const struct ip *ip, unsigned int len, struct timeval *rcvdtime) {
|
||||
const struct ip *ip2;
|
||||
const struct tcp_hdr *tcp;
|
||||
const struct icmp *icmp;
|
||||
bool HostOsScan::processResp(HostOsScanStats *hss, const u8 *pkt, unsigned int len, struct timeval *rcvdtime) {
|
||||
int testno;
|
||||
bool isPktUseful = false;
|
||||
std::list<OFProbe *>::iterator probeI;
|
||||
OFProbe *probe;
|
||||
|
||||
if (len < 20 || len < (4 * ip->ip_hl) + 4U)
|
||||
struct ip ip;
|
||||
if (len < sizeof(ip))
|
||||
return false;
|
||||
memcpy(&ip, pkt, sizeof(ip));
|
||||
if (len < (4 * ip.ip_hl) + 4U)
|
||||
return false;
|
||||
|
||||
len -= 4 * ip->ip_hl;
|
||||
len -= 4 * ip.ip_hl;
|
||||
|
||||
if (ip->ip_p == IPPROTO_TCP) {
|
||||
if (len < 20)
|
||||
if (ip.ip_p == IPPROTO_TCP) {
|
||||
struct tcp_hdr tcp;
|
||||
if (len < sizeof(tcp))
|
||||
return false;
|
||||
tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl));
|
||||
if (len < (unsigned int)(4 * tcp->th_off))
|
||||
const u8 *tcppkt = pkt + 4 * ip.ip_hl;
|
||||
memcpy(&tcp, tcppkt, sizeof(tcp));
|
||||
if (len < (unsigned int)(4 * tcp.th_off))
|
||||
return false;
|
||||
testno = ntohs(tcp->th_dport) - tcpPortBase;
|
||||
testno = ntohs(tcp.th_dport) - tcpPortBase;
|
||||
|
||||
if (testno >= 0 && testno < NUM_SEQ_SAMPLES) {
|
||||
/* TSeq */
|
||||
isPktUseful = processTSeqResp(hss, ip, testno);
|
||||
isPktUseful = processTSeqResp(hss, pkt, testno);
|
||||
|
||||
if (isPktUseful) {
|
||||
hss->ipid.tcp_ipids[testno] = ntohs(ip->ip_id);
|
||||
hss->ipid.tcp_ipids[testno] = ntohs(ip.ip_id);
|
||||
probeI = hss->getActiveProbe(OFP_TSEQ, testno);
|
||||
/* printf("tcp ipid = %d\n", ntohs(ip->ip_id)); */
|
||||
/* printf("tcp ipid = %d\n", ntohs(ip.ip_id)); */
|
||||
}
|
||||
|
||||
/* Use the seq response to do other tests. We don't care if it
|
||||
|
|
@ -1926,17 +1935,17 @@ bool HostOsScan::processResp(HostOsScanStats *hss, const struct ip *ip, unsigned
|
|||
*/
|
||||
if (testno == 0) {
|
||||
/* the first reply is used to do T1 */
|
||||
processT1_7Resp(hss, ip, 0);
|
||||
processT1_7Resp(hss, pkt, 0);
|
||||
}
|
||||
/* the 1st NUM_SEQ_SAMPLES replies are used to do TOps and TWin */
|
||||
processTOpsResp(hss, tcp, testno);
|
||||
processTWinResp(hss, tcp, testno);
|
||||
processTOpsResp(hss, tcppkt, testno);
|
||||
processTWinResp(hss, &tcp, testno);
|
||||
|
||||
} else if (testno >= NUM_SEQ_SAMPLES && testno < NUM_SEQ_SAMPLES + 6) {
|
||||
|
||||
/* TOps/Twin */
|
||||
isPktUseful = processTOpsResp(hss, tcp, testno - NUM_SEQ_SAMPLES);
|
||||
isPktUseful |= processTWinResp(hss, tcp, testno - NUM_SEQ_SAMPLES);
|
||||
isPktUseful = processTOpsResp(hss, tcppkt, testno - NUM_SEQ_SAMPLES);
|
||||
isPktUseful |= processTWinResp(hss, &tcp, testno - NUM_SEQ_SAMPLES);
|
||||
if (isPktUseful) {
|
||||
probeI = hss->getActiveProbe(OFP_TOPS, testno - NUM_SEQ_SAMPLES);
|
||||
}
|
||||
|
|
@ -1944,14 +1953,14 @@ bool HostOsScan::processResp(HostOsScanStats *hss, const struct ip *ip, unsigned
|
|||
} else if (testno == NUM_SEQ_SAMPLES + 6) {
|
||||
|
||||
/* TEcn */
|
||||
isPktUseful = processTEcnResp(hss, ip);
|
||||
isPktUseful = processTEcnResp(hss, pkt);
|
||||
if (isPktUseful) {
|
||||
probeI = hss->getActiveProbe(OFP_TECN, 0);
|
||||
}
|
||||
|
||||
} else if (testno >= NUM_SEQ_SAMPLES + 7 && testno < NUM_SEQ_SAMPLES + 14) {
|
||||
|
||||
isPktUseful = processT1_7Resp(hss, ip, testno - NUM_SEQ_SAMPLES - 7);
|
||||
isPktUseful = processT1_7Resp(hss, pkt, testno - NUM_SEQ_SAMPLES - 7);
|
||||
|
||||
if (isPktUseful) {
|
||||
probeI = hss->getActiveProbe(OFP_T1_7, testno - NUM_SEQ_SAMPLES - 7);
|
||||
|
|
@ -1959,42 +1968,45 @@ bool HostOsScan::processResp(HostOsScanStats *hss, const struct ip *ip, unsigned
|
|||
/* Closed-port TCP IP ID sequence numbers (SEQ.CI). Uses T5, T6, and T7.
|
||||
T5 starts at NUM_SEQ_SAMPLES + 11. */
|
||||
if (testno >= NUM_SEQ_SAMPLES + 11)
|
||||
hss->ipid.tcp_closed_ipids[testno - (NUM_SEQ_SAMPLES + 11)] = ntohs(ip->ip_id);
|
||||
hss->ipid.tcp_closed_ipids[testno - (NUM_SEQ_SAMPLES + 11)] = ntohs(ip.ip_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ip->ip_p == IPPROTO_ICMP) {
|
||||
else if (ip.ip_p == IPPROTO_ICMP) {
|
||||
if (len < 8)
|
||||
return false;
|
||||
icmp = ((struct icmp *)(((char *) ip) + 4 * ip->ip_hl));
|
||||
struct icmp icmp;
|
||||
const u8 *icmppkt = pkt + 4 * ip.ip_hl;
|
||||
memcpy(&icmp, icmppkt, sizeof(icmp));
|
||||
|
||||
/* Is it an icmp echo reply? */
|
||||
if (icmp->icmp_type == ICMP_ECHOREPLY) {
|
||||
testno = ntohs(icmp->icmp_id) - icmpEchoId;
|
||||
if (icmp.icmp_type == ICMP_ECHOREPLY) {
|
||||
testno = ntohs(icmp.icmp_id) - icmpEchoId;
|
||||
if (testno == 0 || testno == 1) {
|
||||
isPktUseful = processTIcmpResp(hss, ip, testno);
|
||||
isPktUseful = processTIcmpResp(hss, pkt, testno);
|
||||
if (isPktUseful) {
|
||||
probeI = hss->getActiveProbe(OFP_TICMP, testno);
|
||||
}
|
||||
|
||||
if (isPktUseful && probeI != hss->probesActive.end() && !(*probeI)->retransmitted) { /* Retransmitted ipid is useless. */
|
||||
hss->ipid.icmp_ipids[testno] = ntohs(ip->ip_id);
|
||||
/* printf("icmp ipid = %d\n", ntohs(ip->ip_id)); */
|
||||
hss->ipid.icmp_ipids[testno] = ntohs(ip.ip_id);
|
||||
/* printf("icmp ipid = %d\n", ntohs(ip.ip_id)); */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Is it a destination port unreachable? */
|
||||
if (icmp->icmp_type == 3 && icmp->icmp_code == 3) {
|
||||
if (icmp.icmp_type == 3 && icmp.icmp_code == 3) {
|
||||
len -= 8; /* icmp destination unreachable header len. */
|
||||
if (len < 28)
|
||||
return false; /* must larger than an ip and an udp header length */
|
||||
ip2 = (struct ip*)((char *)icmp + 8);
|
||||
len -= 4 * ip2->ip_hl;
|
||||
struct ip ip2;
|
||||
memcpy(&ip2, icmppkt + 8, sizeof(ip2));
|
||||
len -= 4 * ip2.ip_hl;
|
||||
if (len < 8)
|
||||
return false;
|
||||
|
||||
isPktUseful = processTUdpResp(hss, ip);
|
||||
isPktUseful = processTUdpResp(hss, pkt);
|
||||
if (isPktUseful) {
|
||||
probeI = hss->getActiveProbe(OFP_TUDP, 0);
|
||||
}
|
||||
|
|
@ -2605,22 +2617,25 @@ void HostOsScan::makeTWinFP(HostOsScanStats *hss) {
|
|||
}
|
||||
|
||||
|
||||
bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int replyNo) {
|
||||
bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const u8 *pkt, int replyNo) {
|
||||
assert(replyNo >= 0 && replyNo < NUM_SEQ_SAMPLES);
|
||||
struct ip ip;
|
||||
memcpy(&ip, pkt, sizeof(ip));
|
||||
|
||||
const struct tcp_hdr *tcp;
|
||||
int seq_response_num; /* response # for sequencing */
|
||||
u32 timestamp = 0; /* TCP timestamp we receive back */
|
||||
|
||||
if (hss->lastipid != 0 && ip->ip_id == hss->lastipid) {
|
||||
if (hss->lastipid != 0 && ip.ip_id == hss->lastipid) {
|
||||
/* Probably a duplicate -- this happens sometimes when scanning localhost */
|
||||
return false;
|
||||
}
|
||||
hss->lastipid = ip->ip_id;
|
||||
hss->lastipid = ip.ip_id;
|
||||
|
||||
tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl));
|
||||
struct tcp_hdr tcp;
|
||||
const u8 *tcppkt = pkt + 4 * ip.ip_hl;
|
||||
memcpy(&tcp, tcppkt, sizeof(tcp));
|
||||
|
||||
if ((tcp->th_flags & TH_RST)) {
|
||||
if ((tcp.th_flags & TH_RST)) {
|
||||
if (hss->si.responses == 0) {
|
||||
error("WARNING: RST from %s port %d -- is this port really open?",
|
||||
hss->target->targetipstr(), hss->openTCPPort);
|
||||
|
|
@ -2628,11 +2643,11 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((tcp->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
|
||||
/* error("DEBUG: response is SYN|ACK to port %hu\n", ntohs(tcp->th_dport)); */
|
||||
/*readtcppacket((char *)ip, ntohs(ip->ip_len));*/
|
||||
if ((tcp.th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
|
||||
/* error("DEBUG: response is SYN|ACK to port %hu\n", ntohs(tcp.th_dport)); */
|
||||
/*readtcppacket((char *)ip, ntohs(ip.ip_len));*/
|
||||
/* We use the ACK value to match up our sent with rcv'd packets */
|
||||
seq_response_num = ntohl(tcp->th_ack) - tcpSeqBase - 1;
|
||||
seq_response_num = ntohl(tcp.th_ack) - tcpSeqBase - 1;
|
||||
/* printf("seq_response_num = %d\treplyNo = %d\n", seq_response_num, replyNo); */
|
||||
|
||||
if (seq_response_num != replyNo) {
|
||||
|
|
@ -2641,9 +2656,9 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
error("Unable to associate os scan response with sent packet for %s.",
|
||||
hss->target->targetipstr());
|
||||
error("Received ack: %lX; sequence sent: %lX. Packet:",
|
||||
(unsigned long) ntohl(tcp->th_ack),
|
||||
(unsigned long) ntohl(tcp.th_ack),
|
||||
(unsigned long) tcpSeqBase);
|
||||
readtcppacket((unsigned char *)ip, ntohs(ip->ip_len));
|
||||
readtcppacket(pkt, ntohs(ip.ip_len));
|
||||
}
|
||||
seq_response_num = replyNo;
|
||||
}
|
||||
|
|
@ -2651,10 +2666,10 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
if (hss->si.seqs[seq_response_num] == 0) {
|
||||
/* New response found! */
|
||||
hss->si.responses++;
|
||||
hss->si.seqs[seq_response_num] = ntohl(tcp->th_seq); /* TCP ISN */
|
||||
hss->si.ipids[seq_response_num] = ntohs(ip->ip_id);
|
||||
hss->si.seqs[seq_response_num] = ntohl(tcp.th_seq); /* TCP ISN */
|
||||
hss->si.ipids[seq_response_num] = ntohs(ip.ip_id);
|
||||
|
||||
if ((gettcpopt_ts(tcp, ×tamp, NULL) == 0))
|
||||
if ((gettcpopt_ts(tcppkt, ×tamp, NULL) == 0))
|
||||
hss->si.ts_seqclass = TS_SEQ_UNSUPPORTED;
|
||||
else {
|
||||
if (timestamp == 0) {
|
||||
|
|
@ -2662,7 +2677,7 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
}
|
||||
}
|
||||
hss->si.timestamps[seq_response_num] = timestamp;
|
||||
/* printf("Response #%d -- ipid=%hu ts=%i\n", seq_response_num, ntohs(ip->ip_id), timestamp); */
|
||||
/* printf("Response #%d -- ipid=%hu ts=%i\n", seq_response_num, ntohs(ip.ip_id), timestamp); */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2672,7 +2687,7 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
}
|
||||
|
||||
|
||||
bool HostOsScan::processTOpsResp(HostOsScanStats *hss, const struct tcp_hdr *tcp, int replyNo) {
|
||||
bool HostOsScan::processTOpsResp(HostOsScanStats *hss, const u8 *tcp, int replyNo) {
|
||||
assert(replyNo >= 0 && replyNo < 6);
|
||||
char ops_buf[256];
|
||||
|
||||
|
|
@ -2708,15 +2723,20 @@ bool HostOsScan::processTWinResp(HostOsScanStats *hss, const struct tcp_hdr *tcp
|
|||
}
|
||||
|
||||
|
||||
bool HostOsScan::processTEcnResp(HostOsScanStats *hss, const struct ip *ip) {
|
||||
bool HostOsScan::processTEcnResp(HostOsScanStats *hss, const u8 *pkt) {
|
||||
char ops_buf[256];
|
||||
char quirks_buf[10];
|
||||
char *p;
|
||||
const struct tcp_hdr *tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl));
|
||||
|
||||
if (hss->FP_TEcn)
|
||||
return false;
|
||||
|
||||
struct ip ip;
|
||||
memcpy(&ip, pkt, sizeof(ip));
|
||||
const u8 *tcppkt = pkt + 4 * ip.ip_hl;
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, tcppkt, sizeof(tcp));
|
||||
|
||||
/* Create the Avals */
|
||||
hss->FP_TEcn = new FingerTest(FingerPrintDef::ECN, *o.reference_FPs->MatchPoints);
|
||||
FingerTest &test = *hss->FP_TEcn;
|
||||
|
|
@ -2724,19 +2744,19 @@ bool HostOsScan::processTEcnResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
test.setAVal("R", "Y");
|
||||
|
||||
/* don't frag flag */
|
||||
if (ntohs(ip->ip_off) & IP_DF)
|
||||
if (ntohs(ip.ip_off) & IP_DF)
|
||||
test.setAVal("DF", "Y");
|
||||
else
|
||||
test.setAVal("DF", "N");
|
||||
|
||||
/* TTL */
|
||||
test.setAVal("T", hss->target->FPR->cp_hex(ip->ip_ttl));
|
||||
test.setAVal("T", hss->target->FPR->cp_hex(ip.ip_ttl));
|
||||
|
||||
/* TCP Window size */
|
||||
test.setAVal("W", hss->target->FPR->cp_hex(ntohs(tcp->th_win)));
|
||||
test.setAVal("W", hss->target->FPR->cp_hex(ntohs(tcp.th_win)));
|
||||
|
||||
/* Now for the TCP options ... */
|
||||
int opsParseResult = get_tcpopt_string(tcp, this->tcpMss, ops_buf, sizeof(ops_buf));
|
||||
int opsParseResult = get_tcpopt_string(tcppkt, this->tcpMss, ops_buf, sizeof(ops_buf));
|
||||
|
||||
if (opsParseResult <= 0) {
|
||||
if (opsParseResult < 0 && o.debugging)
|
||||
|
|
@ -2748,13 +2768,13 @@ bool HostOsScan::processTEcnResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
}
|
||||
|
||||
/* Explicit Congestion Notification support test */
|
||||
if ((tcp->th_flags & TH_ECE) && (tcp->th_flags & TH_CWR))
|
||||
if ((tcp.th_flags & TH_ECE) && (tcp.th_flags & TH_CWR))
|
||||
/* echo back */
|
||||
test.setAVal("CC", "S");
|
||||
else if (tcp->th_flags & TH_ECE)
|
||||
else if (tcp.th_flags & TH_ECE)
|
||||
/* support */
|
||||
test.setAVal("CC", "Y");
|
||||
else if (!(tcp->th_flags & TH_CWR))
|
||||
else if (!(tcp.th_flags & TH_CWR))
|
||||
/* not support */
|
||||
test.setAVal("CC", "N");
|
||||
else
|
||||
|
|
@ -2762,12 +2782,12 @@ bool HostOsScan::processTEcnResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
|
||||
/* TCP miscellaneous quirks test */
|
||||
p = quirks_buf;
|
||||
if (tcp->th_x2) {
|
||||
if (tcp.th_x2) {
|
||||
/* Reserved field of TCP is not zero */
|
||||
assert(p + 1 < quirks_buf + sizeof(quirks_buf));
|
||||
*p++ = 'R';
|
||||
}
|
||||
if (!(tcp->th_flags & TH_URG) && tcp->th_urp) {
|
||||
if (!(tcp.th_flags & TH_URG) && tcp.th_urp) {
|
||||
/* URG pointer value when urg flag not set */
|
||||
assert(p + 1 < quirks_buf + sizeof(quirks_buf));
|
||||
*p++ = 'U';
|
||||
|
|
@ -2779,11 +2799,9 @@ bool HostOsScan::processTEcnResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
}
|
||||
|
||||
|
||||
bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int replyNo) {
|
||||
bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const u8 *pkt, int replyNo) {
|
||||
assert(replyNo >= 0 && replyNo < 7);
|
||||
|
||||
const struct tcp_hdr *tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl));
|
||||
|
||||
int i;
|
||||
int length;
|
||||
char flags_buf[10];
|
||||
|
|
@ -2794,6 +2812,12 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
if (hss->FPtests[FP_T1_7_OFF + replyNo])
|
||||
return false;
|
||||
|
||||
struct ip ip;
|
||||
memcpy(&ip, pkt, sizeof(ip));
|
||||
const u8 *tcppkt = pkt + 4 * ip.ip_hl;
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, tcppkt, sizeof(tcp));
|
||||
|
||||
hss->FPtests[FP_T1_7_OFF + replyNo] = new FingerTest(testid, *o.reference_FPs->MatchPoints);
|
||||
FingerTest &test = *hss->FPtests[FP_T1_7_OFF + replyNo];
|
||||
|
||||
|
|
@ -2802,17 +2826,17 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
test.setAVal("R", "Y");
|
||||
|
||||
/* Next we check whether the Don't Fragment bit is set */
|
||||
if (ntohs(ip->ip_off) & IP_DF)
|
||||
if (ntohs(ip.ip_off) & IP_DF)
|
||||
test.setAVal("DF", "Y");
|
||||
else
|
||||
test.setAVal("DF", "N");
|
||||
|
||||
/* TTL */
|
||||
test.setAVal("T", hss->target->FPR->cp_hex(ip->ip_ttl));
|
||||
test.setAVal("T", hss->target->FPR->cp_hex(ip.ip_ttl));
|
||||
|
||||
if (replyNo != 0) {
|
||||
/* Now we do the TCP Window size */
|
||||
test.setAVal("W", hss->target->FPR->cp_hex(ntohs(tcp->th_win)));
|
||||
test.setAVal("W", hss->target->FPR->cp_hex(ntohs(tcp.th_win)));
|
||||
}
|
||||
|
||||
/* Seq test values:
|
||||
|
|
@ -2821,11 +2845,11 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
A+ = ack + 1
|
||||
O = other
|
||||
*/
|
||||
if (ntohl(tcp->th_seq) == 0)
|
||||
if (ntohl(tcp.th_seq) == 0)
|
||||
test.setAVal("S", "Z");
|
||||
else if (ntohl(tcp->th_seq) == tcpAck)
|
||||
else if (ntohl(tcp.th_seq) == tcpAck)
|
||||
test.setAVal("S", "A");
|
||||
else if (ntohl(tcp->th_seq) == tcpAck + 1)
|
||||
else if (ntohl(tcp.th_seq) == tcpAck + 1)
|
||||
test.setAVal("S", "A+");
|
||||
else
|
||||
test.setAVal("S", "O");
|
||||
|
|
@ -2836,11 +2860,11 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
S+ = syn + 1
|
||||
O = other
|
||||
*/
|
||||
if (ntohl(tcp->th_ack) == 0)
|
||||
if (ntohl(tcp.th_ack) == 0)
|
||||
test.setAVal("A", "Z");
|
||||
else if (ntohl(tcp->th_ack) == tcpSeqBase)
|
||||
else if (ntohl(tcp.th_ack) == tcpSeqBase)
|
||||
test.setAVal("A", "S");
|
||||
else if (ntohl(tcp->th_ack) == tcpSeqBase + 1)
|
||||
else if (ntohl(tcp.th_ack) == tcpSeqBase + 1)
|
||||
test.setAVal("A", "S+");
|
||||
else
|
||||
test.setAVal("A", "O");
|
||||
|
|
@ -2869,7 +2893,7 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
assert(sizeof(flag_defs) / sizeof(flag_defs[0]) < sizeof(flags_buf));
|
||||
p = flags_buf;
|
||||
for (i = 0; i < (int) (sizeof(flag_defs) / sizeof(flag_defs[0])); i++) {
|
||||
if (tcp->th_flags & flag_defs[i].flag)
|
||||
if (tcp.th_flags & flag_defs[i].flag)
|
||||
*p++ = flag_defs[i].c;
|
||||
}
|
||||
*p = '\0';
|
||||
|
|
@ -2879,7 +2903,7 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
char ops_buf[256];
|
||||
|
||||
/* Now for the TCP options ... */
|
||||
int opsParseResult = get_tcpopt_string(tcp, this->tcpMss, ops_buf, sizeof(ops_buf));
|
||||
int opsParseResult = get_tcpopt_string(tcppkt, this->tcpMss, ops_buf, sizeof(ops_buf));
|
||||
if (opsParseResult <= 0) {
|
||||
if (opsParseResult < 0 && o.debugging)
|
||||
error("Option parse error for T%d response from %s.", replyNo, hss->target->targetipstr());
|
||||
|
|
@ -2891,21 +2915,21 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
}
|
||||
|
||||
/* Rst Data CRC32 */
|
||||
length = (int) ntohs(ip->ip_len) - 4 * ip->ip_hl -4 * tcp->th_off;
|
||||
if ((tcp->th_flags & TH_RST) && length>0) {
|
||||
test.setAVal("RD", hss->target->FPR->cp_hex(nbase_crc32(((u8 *)tcp) + 4 * tcp->th_off, length)));
|
||||
length = (int) ntohs(ip.ip_len) - 4 * ip.ip_hl -4 * tcp.th_off;
|
||||
if ((tcp.th_flags & TH_RST) && length>0) {
|
||||
test.setAVal("RD", hss->target->FPR->cp_hex(nbase_crc32(tcppkt + 4 * tcp.th_off, length)));
|
||||
} else {
|
||||
test.setAVal("RD", "0");
|
||||
}
|
||||
|
||||
/* TCP miscellaneous quirks test */
|
||||
p = quirks_buf;
|
||||
if (tcp->th_x2) {
|
||||
if (tcp.th_x2) {
|
||||
/* Reserved field of TCP is not zero */
|
||||
assert(p + 1 < quirks_buf + sizeof(quirks_buf));
|
||||
*p++ = 'R';
|
||||
}
|
||||
if (!(tcp->th_flags & TH_URG) && tcp->th_urp) {
|
||||
if (!(tcp.th_flags & TH_URG) && tcp.th_urp) {
|
||||
/* URG pointer value when urg flag not set */
|
||||
assert(p + 1 < quirks_buf + sizeof(quirks_buf));
|
||||
*p++ = 'U';
|
||||
|
|
@ -2917,31 +2941,32 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
}
|
||||
|
||||
|
||||
bool HostOsScan::processTUdpResp(HostOsScanStats *hss, const struct ip *ip) {
|
||||
bool HostOsScan::processTUdpResp(HostOsScanStats *hss, const u8 *pkt) {
|
||||
|
||||
assert(hss);
|
||||
assert(ip);
|
||||
|
||||
const struct icmp *icmp;
|
||||
const struct ip *ip2;
|
||||
unsigned short checksum;
|
||||
unsigned short *checksumptr;
|
||||
const struct udp_hdr *udp;
|
||||
const unsigned char *datastart, *dataend;
|
||||
assert(pkt);
|
||||
|
||||
if (hss->FP_TUdp)
|
||||
return false;
|
||||
|
||||
icmp = ((struct icmp *)(((char *) ip) + 4 * ip->ip_hl));
|
||||
struct ip ip;
|
||||
memcpy(&ip, pkt, sizeof(ip));
|
||||
const u8 *icmppkt = pkt + 4 * ip.ip_hl;
|
||||
struct icmp icmp;
|
||||
memcpy(&icmp, icmppkt, sizeof(icmp));
|
||||
|
||||
/* Make sure this is icmp port unreachable. */
|
||||
assert(icmp->icmp_type == 3 && icmp->icmp_code == 3);
|
||||
assert(icmp.icmp_type == 3 && icmp.icmp_code == 3);
|
||||
|
||||
ip2 = (struct ip*)((char *)icmp + 8);
|
||||
udp = (struct udp_hdr *)((char *)ip2 + 4 * ip2->ip_hl);
|
||||
struct ip ip2;
|
||||
const u8 *ip2pkt = icmppkt + 8;
|
||||
memcpy(&ip2, ip2pkt, sizeof(ip2));
|
||||
struct udp_hdr udp;
|
||||
const u8 *udppkt = ip2pkt + 4 * ip2.ip_hl;
|
||||
memcpy(&udp, udppkt, sizeof(udp));
|
||||
|
||||
/* The ports should match. */
|
||||
if (ntohs(udp->uh_sport) != hss->upi.sport || ntohs(udp->uh_dport) != hss->upi.dport) {
|
||||
if (ntohs(udp.uh_sport) != hss->upi.sport || ntohs(udp.uh_dport) != hss->upi.dport) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2956,37 +2981,37 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
hss->target->FPR->osscan_closedudpport = hss->upi.dport;
|
||||
|
||||
/* Now let us do an easy one, Don't fragment */
|
||||
if (ntohs(ip->ip_off) & IP_DF)
|
||||
if (ntohs(ip.ip_off) & IP_DF)
|
||||
test.setAVal("DF", "Y");
|
||||
else
|
||||
test.setAVal("DF", "N");
|
||||
|
||||
/* TTL */
|
||||
test.setAVal("T", hss->target->FPR->cp_hex(ip->ip_ttl));
|
||||
test.setAVal("T", hss->target->FPR->cp_hex(ip.ip_ttl));
|
||||
|
||||
/* Now we look at the IP datagram length that was returned, some
|
||||
machines send more of the original packet back than others */
|
||||
test.setAVal("IPL", hss->target->FPR->cp_hex(ntohs(ip->ip_len)));
|
||||
test.setAVal("IPL", hss->target->FPR->cp_hex(ntohs(ip.ip_len)));
|
||||
|
||||
/* unused filed not zero in Destination Unreachable Message */
|
||||
test.setAVal("UN", hss->target->FPR->cp_hex(ntohl(icmp->icmp_void)));
|
||||
test.setAVal("UN", hss->target->FPR->cp_hex(ntohl(icmp.icmp_void)));
|
||||
|
||||
/* OK, lets check the returned IP length, some systems @$@ this
|
||||
up */
|
||||
if (ntohs(ip2->ip_len) == 328)
|
||||
if (ntohs(ip2.ip_len) == 328)
|
||||
test.setAVal("RIPL", "G");
|
||||
else
|
||||
test.setAVal("RIPL", hss->target->FPR->cp_hex(ntohs(ip2->ip_len)));
|
||||
test.setAVal("RIPL", hss->target->FPR->cp_hex(ntohs(ip2.ip_len)));
|
||||
|
||||
/* This next test doesn't work on Solaris because the lamers
|
||||
overwrite our ip_id */
|
||||
#if !defined(SOLARIS) && !defined(SUNOS) && !defined(IRIX) && !defined(HPUX)
|
||||
|
||||
/* Now lets see how they treated the ID we sent ... */
|
||||
if (ntohs(ip2->ip_id) == hss->upi.ipid)
|
||||
if (ntohs(ip2.ip_id) == hss->upi.ipid)
|
||||
test.setAVal("RID", "G"); /* The good "expected" value */
|
||||
else
|
||||
test.setAVal("RID", hss->target->FPR->cp_hex(ntohs(ip2->ip_id)));
|
||||
test.setAVal("RID", hss->target->FPR->cp_hex(ntohs(ip2.ip_id)));
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -2994,14 +3019,14 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
|
||||
/* Thanks to some machines not having struct ip member ip_sum we
|
||||
have to go with this BS */
|
||||
checksumptr = (unsigned short *) ((char *) ip2 + 10);
|
||||
checksum = *checksumptr;
|
||||
u16 *checksumptr = (u16 *) (ip2pkt + 10);
|
||||
u16 checksum = *checksumptr;
|
||||
|
||||
if (checksum == 0) {
|
||||
test.setAVal("RIPCK", "Z");
|
||||
} else {
|
||||
*checksumptr = 0;
|
||||
if (in_cksum((unsigned short *)ip2, 20) == checksum) {
|
||||
if (in_cksum((const u16 *)ip2pkt, 20) == checksum) {
|
||||
test.setAVal("RIPCK", "G"); /* The "expected" good value */
|
||||
} else {
|
||||
test.setAVal("RIPCK", "I"); /* They modified it */
|
||||
|
|
@ -3010,14 +3035,14 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
}
|
||||
|
||||
/* UDP checksum */
|
||||
if (udp->uh_sum == hss->upi.udpck)
|
||||
if (udp.uh_sum == hss->upi.udpck)
|
||||
test.setAVal("RUCK", "G"); /* The "expected" good value */
|
||||
else
|
||||
test.setAVal("RUCK", hss->target->FPR->cp_hex(ntohs(udp->uh_sum)));
|
||||
test.setAVal("RUCK", hss->target->FPR->cp_hex(ntohs(udp.uh_sum)));
|
||||
|
||||
/* Finally we ensure the data is OK */
|
||||
datastart = ((unsigned char *)udp) + 8;
|
||||
dataend = (unsigned char *) ip + ntohs(ip->ip_len);
|
||||
const u8 *datastart = udppkt + 8;
|
||||
const u8 *dataend = pkt + ntohs(ip.ip_len);
|
||||
|
||||
while (datastart < dataend) {
|
||||
if (*datastart != hss->upi.patternbyte)
|
||||
|
|
@ -3031,27 +3056,28 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, const struct ip *ip) {
|
|||
|
||||
/* Count hop count */
|
||||
if (hss->distance == -1) {
|
||||
hss->distance = this->udpttl - ip2->ip_ttl + 1;
|
||||
hss->distance = this->udpttl - ip2.ip_ttl + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, const struct ip *ip, int replyNo) {
|
||||
bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, const u8 *pkt, int replyNo) {
|
||||
assert(replyNo == 0 || replyNo == 1);
|
||||
|
||||
const struct ip *ip1, *ip2;
|
||||
const struct icmp *icmp1, *icmp2;
|
||||
unsigned short value1, value2;
|
||||
|
||||
if (hss->FP_TIcmp)
|
||||
return false;
|
||||
|
||||
struct ip ip;
|
||||
memcpy(&ip, pkt, sizeof(ip));
|
||||
|
||||
if (hss->icmpEchoReply == NULL) {
|
||||
/* This is the first icmp reply we get, store it and return. */
|
||||
hss->icmpEchoReply = (struct ip *) safe_malloc(ntohs(ip->ip_len));
|
||||
memcpy(hss->icmpEchoReply, ip, ntohs(ip->ip_len));
|
||||
hss->icmpEchoReply = (u8 *) safe_malloc(ntohs(ip.ip_len));
|
||||
memcpy(hss->icmpEchoReply, pkt, ntohs(ip.ip_len));
|
||||
hss->storedIcmpReply = replyNo;
|
||||
return true;
|
||||
} else if (hss->storedIcmpReply == replyNo) {
|
||||
|
|
@ -3059,19 +3085,31 @@ bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
return false;
|
||||
}
|
||||
|
||||
const struct ip *ip1, *ip2;
|
||||
const u8 *ip1pkt, *ip2pkt;
|
||||
struct ip tmp;
|
||||
/* Ok, now we get another reply. */
|
||||
if (hss->storedIcmpReply == 0) {
|
||||
ip1 = hss->icmpEchoReply;
|
||||
ip2 = ip;
|
||||
ip1pkt = hss->icmpEchoReply;
|
||||
memcpy(&tmp, ip1pkt, sizeof(tmp));
|
||||
ip1 = &tmp;
|
||||
|
||||
ip2pkt = pkt;
|
||||
ip2 = &ip;
|
||||
} else {
|
||||
ip1 = ip;
|
||||
ip2 = hss->icmpEchoReply;
|
||||
ip2pkt = hss->icmpEchoReply;
|
||||
memcpy(&tmp, ip2pkt, sizeof(tmp));
|
||||
ip2 = &tmp;
|
||||
|
||||
ip1pkt = pkt;
|
||||
ip1 = &ip;
|
||||
}
|
||||
|
||||
icmp1 = ((struct icmp *)(((char *) ip1) + 4 * ip1->ip_hl));
|
||||
icmp2 = ((struct icmp *)(((char *) ip2) + 4 * ip2->ip_hl));
|
||||
struct icmp icmp1, icmp2;
|
||||
memcpy(&icmp1, ip1pkt + 4 * ip1->ip_hl, sizeof(icmp1));
|
||||
memcpy(&icmp2, ip2pkt + 4 * ip2->ip_hl, sizeof(icmp2));
|
||||
|
||||
assert(icmp1->icmp_type == 0 && icmp2->icmp_type == 0);
|
||||
assert(icmp1.icmp_type == 0 && icmp2.icmp_type == 0);
|
||||
|
||||
hss->FP_TIcmp= new FingerTest(FingerPrintDef::IE, *o.reference_FPs->MatchPoints);
|
||||
FingerTest &test = *hss->FP_TIcmp;
|
||||
|
|
@ -3107,8 +3145,8 @@ bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
* S. Both use the Code that the sender uses;
|
||||
* O. Other.
|
||||
*/
|
||||
value1 = icmp1->icmp_code;
|
||||
value2 = icmp2->icmp_code;
|
||||
value1 = icmp1.icmp_code;
|
||||
value2 = icmp2.icmp_code;
|
||||
if (value1 == value2) {
|
||||
if (value1 == 0)
|
||||
test.setAVal("CD", "Z");
|
||||
|
|
@ -3125,17 +3163,19 @@ bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, const struct ip *ip, int
|
|||
}
|
||||
|
||||
|
||||
int HostOsScan::get_tcpopt_string(const struct tcp_hdr *tcp, int mss, char *result, int maxlen) const {
|
||||
int HostOsScan::get_tcpopt_string(const u8 *tcp, int mss, char *result, int maxlen) const {
|
||||
char *p;
|
||||
const char *q;
|
||||
const u8 *q;
|
||||
u16 tmpshort;
|
||||
u32 tmpword;
|
||||
int length;
|
||||
int opcode;
|
||||
|
||||
p = result;
|
||||
length = (tcp->th_off * 4) - sizeof(struct tcp_hdr);
|
||||
q = ((char *)tcp) + sizeof(struct tcp_hdr);
|
||||
struct tcp_hdr hdr;
|
||||
memcpy(&hdr, tcp, sizeof(hdr));
|
||||
length = (hdr.th_off * 4) - sizeof(struct tcp_hdr);
|
||||
q = tcp + sizeof(struct tcp_hdr);
|
||||
|
||||
/*
|
||||
* Example parsed result: M5B4ST11NW2
|
||||
|
|
|
|||
18
osscan2.h
18
osscan2.h
|
|
@ -319,7 +319,7 @@ class HostOsScanStats {
|
|||
int TWinReplyNum; /* how many TWin replies are received. */
|
||||
int TOpsReplyNum; /* how many TOps replies are received. Actually it is the same with TOpsReplyNum. */
|
||||
|
||||
struct ip *icmpEchoReply; /* To store one of the two icmp replies */
|
||||
u8 *icmpEchoReply; /* To store one of the two icmp replies */
|
||||
int storedIcmpReply; /* Which one of the two icmp replies is stored? */
|
||||
|
||||
struct udpprobeinfo upi; /* info of the udp probe we sent */
|
||||
|
|
@ -364,7 +364,7 @@ class HostOsScan {
|
|||
void sendNextProbe(HostOsScanStats *hss);
|
||||
|
||||
/* Process one response. If the response is useful, return true. */
|
||||
bool processResp(HostOsScanStats *hss, const struct ip *ip, unsigned int len, struct timeval *rcvdtime);
|
||||
bool processResp(HostOsScanStats *hss, const u8 *ip, unsigned int len, struct timeval *rcvdtime);
|
||||
|
||||
/* Make up the fingerprint. */
|
||||
void makeFP(HostOsScanStats *hss);
|
||||
|
|
@ -403,13 +403,13 @@ private:
|
|||
void sendTUdpProbe(HostOsScanStats *hss, int probeNo);
|
||||
void sendTIcmpProbe(HostOsScanStats *hss, int probeNo);
|
||||
/* Response process functions. */
|
||||
bool processTSeqResp(HostOsScanStats *hss, const struct ip *ip, int replyNo);
|
||||
bool processTOpsResp(HostOsScanStats *hss, const struct tcp_hdr *tcp, int replyNo);
|
||||
bool processTSeqResp(HostOsScanStats *hss, const u8 *ip, int replyNo);
|
||||
bool processTOpsResp(HostOsScanStats *hss, const u8 *tcp, int replyNo);
|
||||
bool processTWinResp(HostOsScanStats *hss, const struct tcp_hdr *tcp, int replyNo);
|
||||
bool processTEcnResp(HostOsScanStats *hss, const struct ip *ip);
|
||||
bool processT1_7Resp(HostOsScanStats *hss, const struct ip *ip, int replyNo);
|
||||
bool processTUdpResp(HostOsScanStats *hss, const struct ip *ip);
|
||||
bool processTIcmpResp(HostOsScanStats *hss, const struct ip *ip, int replyNo);
|
||||
bool processTEcnResp(HostOsScanStats *hss, const u8 *ip);
|
||||
bool processT1_7Resp(HostOsScanStats *hss, const u8 *ip, int replyNo);
|
||||
bool processTUdpResp(HostOsScanStats *hss, const u8 *ip);
|
||||
bool processTIcmpResp(HostOsScanStats *hss, const u8 *ip, int replyNo);
|
||||
|
||||
/* Generic sending functions used by the above probe functions. */
|
||||
int send_tcp_probe(HostOsScanStats *hss,
|
||||
|
|
@ -428,7 +428,7 @@ private:
|
|||
void makeTOpsFP(HostOsScanStats *hss);
|
||||
void makeTWinFP(HostOsScanStats *hss);
|
||||
|
||||
int get_tcpopt_string(const struct tcp_hdr *tcp, int mss, char *result, int maxlen) const;
|
||||
int get_tcpopt_string(const u8 *tcp, int mss, char *result, int maxlen) const;
|
||||
|
||||
int rawsd; /* Raw socket descriptor */
|
||||
netutil_eth_t *ethsd; /* Ethernet handle */
|
||||
|
|
|
|||
|
|
@ -392,9 +392,7 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
bool adjust_timing = true;
|
||||
struct timeval rcvdtime;
|
||||
struct link_header linkhdr;
|
||||
const struct ip *ip_tmp;
|
||||
unsigned int bytes;
|
||||
const struct ppkt *ping;
|
||||
long to_usec;
|
||||
HostScanStats *hss = NULL;
|
||||
std::list<UltraProbe *>::iterator probeI;
|
||||
|
|
@ -412,10 +410,11 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
to_usec = TIMEVAL_SUBTRACT(*stime, USI->now);
|
||||
if (to_usec < 2000)
|
||||
to_usec = 2000;
|
||||
ip_tmp = (struct ip *) readip_pcap(USI->pd, &bytes, to_usec, &rcvdtime,
|
||||
const u8 *pkt = readip_pcap(USI->pd, &bytes, to_usec, &rcvdtime,
|
||||
&linkhdr, true);
|
||||
|
||||
gettimeofday(&USI->now, NULL);
|
||||
if (!ip_tmp) {
|
||||
if (!pkt) {
|
||||
if (TIMEVAL_BEFORE(*stime, USI->now)) {
|
||||
timedout = true;
|
||||
break;
|
||||
|
|
@ -435,30 +434,34 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
*/
|
||||
|
||||
datalen = bytes;
|
||||
data = ip_get_data(ip_tmp, &datalen, &hdr);
|
||||
data = ip_get_data(pkt, &datalen, &hdr);
|
||||
if (data == NULL)
|
||||
continue;
|
||||
// If it's not sent to us, we don't care.
|
||||
if (sockaddr_storage_cmp(USI->SourceSockAddr(), &hdr.dst) != 0)
|
||||
continue;
|
||||
|
||||
struct ip ip_tmp;
|
||||
memcpy(&ip_tmp, pkt, sizeof(ip_tmp));
|
||||
|
||||
/* First check if it is ICMP, TCP, or UDP */
|
||||
if (hdr.proto == IPPROTO_ICMP || hdr.proto == IPPROTO_ICMPV6) {
|
||||
/* if it is our response */
|
||||
ping = (struct ppkt *) data;
|
||||
if (bytes < 8U) {
|
||||
if (!ip_tmp->ip_off)
|
||||
if (!ip_tmp.ip_off)
|
||||
error("Supposed ping packet is only %d bytes long!", bytes);
|
||||
continue;
|
||||
}
|
||||
|
||||
current_reason = icmp_to_reason(hdr.proto, ping->type, ping->code);
|
||||
struct ppkt ping;
|
||||
memcpy(&ping, data, sizeof(ping));
|
||||
current_reason = icmp_to_reason(hdr.proto, ping.type, ping.code);
|
||||
|
||||
/* Echo reply, Timestamp reply, or Address Mask Reply. RFCs 792 and 950. */
|
||||
/* ICMPv6 Echo reply */
|
||||
if (USI->ptech.rawicmpscan
|
||||
&& ((hdr.proto == IPPROTO_ICMP && (ping->type == 0 || ping->type == 14 || ping->type == 18))
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping->type == 129))) {
|
||||
&& ((hdr.proto == IPPROTO_ICMP && (ping.type == 0 || ping.type == 14 || ping.type == 18))
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping.type == 129))) {
|
||||
hss = USI->findHost(&hdr.src);
|
||||
if (!hss)
|
||||
continue; // Not from a host that interests us
|
||||
|
|
@ -485,23 +488,22 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
probeI--;
|
||||
probe = *probeI;
|
||||
|
||||
if (!icmp_probe_match(USI, probe, ping, &hdr.src, &hdr.dst, hdr.proto, hdr.ipid))
|
||||
if (!icmp_probe_match(USI, probe, &ping, &hdr.src, &hdr.dst, hdr.proto, hdr.ipid))
|
||||
continue;
|
||||
|
||||
goodone = true;
|
||||
newstate = HOST_UP;
|
||||
|
||||
if (o.debugging)
|
||||
log_write(LOG_STDOUT, "We got a ping packet back from %s: id = %d seq = %d checksum = %d\n", inet_ntop_ez(&hdr.src, sizeof(hdr.src)), ping->id, ping->seq, ping->checksum);
|
||||
log_write(LOG_STDOUT, "We got a ping packet back from %s: id = %d seq = %d checksum = %d\n", inet_ntop_ez(&hdr.src, sizeof(hdr.src)), ping.id, ping.seq, ping.checksum);
|
||||
}
|
||||
}
|
||||
// For ICMP, the reply of TCP/UDP/ICMP packets can be Destination unreachable, source quench, or time exceeded
|
||||
/* For ICMPv6, the reply of TCP/UDP/ICMPV6 packets can be Destination Unreachable,
|
||||
* Packet Too Big, Time Exceeded and Parameter Problem.*/
|
||||
else if ((hdr.proto == IPPROTO_ICMP && (ping->type == 3 || ping->type
|
||||
== 4 || ping->type == 11))
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && (ping->type == 1 || ping->type == 2
|
||||
|| ping->type == 3 || ping->type == 4))) {
|
||||
else if ((hdr.proto == IPPROTO_ICMP && (ping.type == 3 || ping.type == 4 || ping.type == 11))
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && (ping.type == 1 || ping.type == 2
|
||||
|| ping.type == 3 || ping.type == 4))) {
|
||||
const void *encaps_data;
|
||||
unsigned int encaps_len;
|
||||
struct abstract_ip_hdr encaps_hdr;
|
||||
|
|
@ -557,24 +559,29 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
if ((encaps_hdr.proto == IPPROTO_ICMP || encaps_hdr.proto == IPPROTO_ICMPV6)
|
||||
&& USI->ptech.rawicmpscan) {
|
||||
/* The response was based on a ping packet we sent */
|
||||
if (probe->icmpid() != ntohs(((struct icmp *) encaps_data)->icmp_id))
|
||||
struct icmp icmp;
|
||||
memcpy(&icmp, encaps_data, sizeof(icmp));
|
||||
if (probe->icmpid() != ntohs(icmp.icmp_id))
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_TCP && USI->ptech.rawtcpscan) {
|
||||
const struct tcp_hdr *tcp = (struct tcp_hdr *) encaps_data;
|
||||
if (probe->dport() != ntohs(tcp->th_dport) ||
|
||||
probe->sport() != ntohs(tcp->th_sport) ||
|
||||
probe->tcpseq() != ntohl(tcp->th_seq))
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, encaps_data, sizeof(tcp));
|
||||
if (probe->dport() != ntohs(tcp.th_dport) ||
|
||||
probe->sport() != ntohs(tcp.th_sport) ||
|
||||
probe->tcpseq() != ntohl(tcp.th_seq))
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_UDP && USI->ptech.rawudpscan) {
|
||||
const struct udp_hdr *udp = (struct udp_hdr *) encaps_data;
|
||||
if (probe->dport() != ntohs(udp->uh_dport) ||
|
||||
probe->sport() != ntohs(udp->uh_sport))
|
||||
struct udp_hdr udp;
|
||||
memcpy(&udp, encaps_data, sizeof(udp));
|
||||
if (probe->dport() != ntohs(udp.uh_dport) ||
|
||||
probe->sport() != ntohs(udp.uh_sport))
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_SCTP && USI->ptech.rawsctpscan) {
|
||||
const struct sctp_hdr *sctp = (struct sctp_hdr *) encaps_data;
|
||||
if (probe->dport() != ntohs(sctp->sh_dport) ||
|
||||
probe->sport() != ntohs(sctp->sh_sport) ||
|
||||
probe->sctpvtag() != ntohl(sctp->sh_vtag))
|
||||
struct sctp_hdr sctp;
|
||||
memcpy(&sctp, encaps_data, sizeof(sctp));
|
||||
if (probe->dport() != ntohs(sctp.sh_dport) ||
|
||||
probe->sport() != ntohs(sctp.sh_sport) ||
|
||||
probe->sctpvtag() != ntohl(sctp.sh_vtag))
|
||||
continue;
|
||||
} else if (USI->ptech.rawprotoscan) {
|
||||
/* Success; we already know that the address and protocol match. */
|
||||
|
|
@ -591,11 +598,11 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
continue;
|
||||
|
||||
/* Destination unreachable. */
|
||||
if ((hdr.proto == IPPROTO_ICMP && ping->type == 3)
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping->type == 1)) {
|
||||
if ((hdr.proto == IPPROTO_ICMP && ping.type == 3)
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping.type == 1)) {
|
||||
// If it's Port or Proto unreachable and the address matches, it's up.
|
||||
if (((hdr.proto == IPPROTO_ICMP && (ping->code == 2 || ping->code == 3))
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping->code == 4))
|
||||
if (((hdr.proto == IPPROTO_ICMP && (ping.code == 2 || ping.code == 3))
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping.code == 4))
|
||||
&& sockaddr_storage_cmp(hss->target->TargetSockAddr(), &hdr.src) == 0) {
|
||||
/* The ICMP or ICMPv6 error came directly from the target, so it's up. */
|
||||
goodone = true;
|
||||
|
|
@ -619,8 +626,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
log_write(LOG_STDOUT, "Got destination unreachable for %s\n", hss->target->targetipstr());
|
||||
}
|
||||
}
|
||||
} else if ((hdr.proto == IPPROTO_ICMP && ping->type == 11)
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping->type == 3)) {
|
||||
} else if ((hdr.proto == IPPROTO_ICMP && ping.type == 11)
|
||||
|| (hdr.proto == IPPROTO_ICMPV6 && ping.type == 3)) {
|
||||
if (o.debugging)
|
||||
log_write(LOG_STDOUT, "Got Time Exceeded for %s\n", hss->target->targetipstr());
|
||||
goodone = 1;
|
||||
|
|
@ -628,35 +635,36 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
/* I don't want anything to do with timing this. */
|
||||
adjust_timing = false;
|
||||
} else if (hdr.proto == IPPROTO_ICMP) {
|
||||
if (ping->type == 4) {
|
||||
if (ping.type == 4) {
|
||||
if (o.debugging)
|
||||
log_write(LOG_STDOUT, "Got ICMP source quench\n");
|
||||
usleep(50000);
|
||||
} else {
|
||||
if (o.debugging) {
|
||||
log_write(LOG_STDOUT, "Got ICMP message type %d code %d\n",
|
||||
ping->type, ping->code);
|
||||
ping.type, ping.code);
|
||||
}
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_ICMPV6) {
|
||||
if (ping->type == 4) {
|
||||
if (ping.type == 4) {
|
||||
if (o.debugging)
|
||||
log_write(LOG_STDOUT, "Got ICMPv6 Parameter Problem\n");
|
||||
} else {
|
||||
if (o.debugging)
|
||||
log_write(LOG_STDOUT, "Got ICMPv6 message type %d code %d\n",
|
||||
ping->type, ping->code);
|
||||
ping.type, ping.code);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_TCP && USI->ptech.rawtcpscan) {
|
||||
const struct tcp_hdr *tcp = (struct tcp_hdr *) data;
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, data, sizeof(tcp));
|
||||
/* Check that the packet has useful flags. */
|
||||
if (o.discovery_ignore_rst
|
||||
&& (tcp->th_flags & TH_RST))
|
||||
&& (tcp.th_flags & TH_RST))
|
||||
continue;
|
||||
else if (!(tcp->th_flags & TH_RST)
|
||||
&& ((tcp->th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK)))
|
||||
else if (!(tcp.th_flags & TH_RST)
|
||||
&& ((tcp.th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK)))
|
||||
continue;
|
||||
|
||||
/* Now ensure this host is even in the incomplete list */
|
||||
|
|
@ -666,8 +674,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
setTargetMACIfAvailable(hss->target, &linkhdr, &hdr.src, 0);
|
||||
probeI = hss->probes_outstanding.end();
|
||||
listsz = hss->num_probes_outstanding();
|
||||
u16 sport = ntohs(tcp->th_sport);
|
||||
u16 dport = ntohs(tcp->th_dport);
|
||||
u16 sport = ntohs(tcp.th_sport);
|
||||
u16 dport = ntohs(tcp.th_dport);
|
||||
|
||||
goodone = false;
|
||||
|
||||
|
|
@ -678,7 +686,7 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
|
||||
if (!probe->check_proto_port(hdr.proto, dport, sport))
|
||||
continue;
|
||||
if (!tcp_probe_match(USI, probe, tcp, &hdr.src, &hdr.dst, hdr.ipid))
|
||||
if (!tcp_probe_match(USI, probe, &tcp, &hdr.src, &hdr.dst, hdr.ipid))
|
||||
continue;
|
||||
|
||||
goodone = true;
|
||||
|
|
@ -686,13 +694,13 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
|
||||
/* Fill out the reason. */
|
||||
if (o.pingtype & PINGTYPE_TCP_USE_SYN) {
|
||||
if (tcp->th_flags & TH_RST) {
|
||||
if (tcp.th_flags & TH_RST) {
|
||||
current_reason = ER_RESETPEER;
|
||||
} else if ((tcp->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
|
||||
} else if ((tcp.th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
|
||||
current_reason = ER_SYNACK;
|
||||
}
|
||||
} else if (o.pingtype & PINGTYPE_TCP_USE_ACK) {
|
||||
if (tcp->th_flags & TH_RST)
|
||||
if (tcp.th_flags & TH_RST)
|
||||
current_reason = ER_RESETPEER;
|
||||
}
|
||||
|
||||
|
|
@ -700,7 +708,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
log_write(LOG_STDOUT, "We got a TCP ping packet back from %s port %hu (trynum = %d)\n", inet_ntop_ez(&hdr.src, sizeof(hdr.src)), sport, probe->get_tryno());
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_UDP && USI->ptech.rawudpscan) {
|
||||
const struct udp_hdr *udp = (struct udp_hdr *) data;
|
||||
struct udp_hdr udp;
|
||||
memcpy(&udp, data, sizeof(udp));
|
||||
/* Search for this host on the incomplete list */
|
||||
hss = USI->findHost(&hdr.src);
|
||||
if (!hss)
|
||||
|
|
@ -710,8 +719,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
listsz = hss->num_probes_outstanding();
|
||||
goodone = false;
|
||||
|
||||
u16 sport = ntohs(udp->uh_sport);
|
||||
u16 dport = ntohs(udp->uh_dport);
|
||||
u16 sport = ntohs(udp.uh_sport);
|
||||
u16 dport = ntohs(udp.uh_dport);
|
||||
|
||||
for (probenum = 0; probenum < listsz && !goodone; probenum++) {
|
||||
probeI--;
|
||||
|
|
@ -736,9 +745,6 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
log_write(LOG_STDOUT, "In response to UDP-ping, we got UDP packet back from %s port %hu (trynum = %d)\n", inet_ntop_ez(&hdr.src, sizeof(hdr.src)), sport, probe->get_tryno());
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_SCTP && USI->ptech.rawsctpscan) {
|
||||
const struct sctp_hdr *sctp = (struct sctp_hdr *) data;
|
||||
const struct dnet_sctp_chunkhdr *chunk =
|
||||
(struct dnet_sctp_chunkhdr *) ((u8 *) sctp + 12);
|
||||
/* Search for this host on the incomplete list */
|
||||
hss = USI->findHost(&hdr.src);
|
||||
if (!hss)
|
||||
|
|
@ -747,8 +753,13 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
listsz = hss->num_probes_outstanding();
|
||||
goodone = false;
|
||||
|
||||
u16 sport = ntohs(sctp->sh_sport);
|
||||
u16 dport = ntohs(sctp->sh_dport);
|
||||
struct sctp_hdr sctp;
|
||||
memcpy(&sctp, data, sizeof(sctp));
|
||||
struct dnet_sctp_chunkhdr chunk;
|
||||
memcpy(&chunk, (u8 *)data + 12, sizeof(chunk));
|
||||
|
||||
u16 sport = ntohs(sctp.sh_sport);
|
||||
u16 dport = ntohs(sctp.sh_dport);
|
||||
|
||||
for (probenum = 0; probenum < listsz && !goodone; probenum++) {
|
||||
probeI--;
|
||||
|
|
@ -767,9 +778,9 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
|
||||
goodone = true;
|
||||
newstate = HOST_UP;
|
||||
if (chunk->sch_type == SCTP_INIT_ACK) {
|
||||
if (chunk.sch_type == SCTP_INIT_ACK) {
|
||||
current_reason = ER_INITACK;
|
||||
} else if (chunk->sch_type == SCTP_ABORT) {
|
||||
} else if (chunk.sch_type == SCTP_ABORT) {
|
||||
current_reason = ER_ABORT;
|
||||
} else {
|
||||
current_reason = ER_UNKNOWN;
|
||||
|
|
@ -1670,7 +1681,8 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
}
|
||||
|
||||
if (hdr.proto == IPPROTO_TCP && !USI->prot_scan) {
|
||||
const struct tcp_hdr *tcp = (struct tcp_hdr *) data;
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, data, sizeof(tcp));
|
||||
/* Now ensure this host is even in the incomplete list */
|
||||
hss = USI->findHost(&hdr.src);
|
||||
if (!hss)
|
||||
|
|
@ -1678,8 +1690,8 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
setTargetMACIfAvailable(hss->target, &linkhdr, &hdr.src, 0);
|
||||
probeI = hss->probes_outstanding.end();
|
||||
listsz = hss->num_probes_outstanding();
|
||||
u16 sport = ntohs(tcp->th_sport);
|
||||
u16 dport = ntohs(tcp->th_dport);
|
||||
u16 sport = ntohs(tcp.th_sport);
|
||||
u16 dport = ntohs(tcp.th_dport);
|
||||
|
||||
goodone = false;
|
||||
|
||||
|
|
@ -1690,29 +1702,29 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
|
||||
if (!probe->check_proto_port(hdr.proto, dport, sport))
|
||||
continue;
|
||||
if (!tcp_probe_match(USI, probe, tcp, &hdr.src, &hdr.dst, hdr.ipid))
|
||||
if (!tcp_probe_match(USI, probe, &tcp, &hdr.src, &hdr.dst, hdr.ipid))
|
||||
continue;
|
||||
|
||||
if (!probe->isPing()) {
|
||||
/* Now that response has been matched to a probe, I interpret it */
|
||||
if (USI->scantype == SYN_SCAN && (tcp->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
|
||||
if (USI->scantype == SYN_SCAN && (tcp.th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
|
||||
/* Yeah! An open port */
|
||||
newstate = PORT_OPEN;
|
||||
current_reason = ER_SYNACK;
|
||||
} else if (tcp->th_flags & TH_RST) {
|
||||
} else if (tcp.th_flags & TH_RST) {
|
||||
current_reason = ER_RESETPEER;
|
||||
if (USI->scantype == WINDOW_SCAN ) {
|
||||
newstate = (tcp->th_win) ? PORT_OPEN : PORT_CLOSED;
|
||||
newstate = (tcp.th_win) ? PORT_OPEN : PORT_CLOSED;
|
||||
} else if (USI->scantype == ACK_SCAN) {
|
||||
newstate = PORT_UNFILTERED;
|
||||
} else newstate = PORT_CLOSED;
|
||||
} else if (USI->scantype == SYN_SCAN && (tcp->th_flags & TH_SYN)) {
|
||||
} else if (USI->scantype == SYN_SCAN && (tcp.th_flags & TH_SYN)) {
|
||||
/* A SYN from a TCP Split Handshake - https://nmap.org/misc/split-handshake.pdf - open port */
|
||||
newstate = PORT_OPEN;
|
||||
current_reason = ER_SYN;
|
||||
} else {
|
||||
if (o.debugging)
|
||||
error("Received scan response with unexpected TCP flags: %d", tcp->th_flags);
|
||||
error("Received scan response with unexpected TCP flags: %d", tcp.th_flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1720,8 +1732,6 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
goodone = true;
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_SCTP && !USI->prot_scan) {
|
||||
const struct sctp_hdr *sctp = (struct sctp_hdr *) data;
|
||||
const struct dnet_sctp_chunkhdr *chunk = (struct dnet_sctp_chunkhdr *) ((u8 *) sctp + 12);
|
||||
|
||||
/* Now ensure this host is even in the incomplete list */
|
||||
hss = USI->findHost(&hdr.src);
|
||||
|
|
@ -1733,8 +1743,13 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
|
||||
goodone = false;
|
||||
|
||||
u16 sport = ntohs(sctp->sh_sport);
|
||||
u16 dport = ntohs(sctp->sh_dport);
|
||||
struct sctp_hdr sctp;
|
||||
memcpy(&sctp, data, sizeof(sctp));
|
||||
struct dnet_sctp_chunkhdr chunk;
|
||||
memcpy(&chunk, (u8 *)data + 12, sizeof(chunk));
|
||||
|
||||
u16 sport = ntohs(sctp.sh_sport);
|
||||
u16 dport = ntohs(sctp.sh_dport);
|
||||
|
||||
/* Find the probe that provoked this response. */
|
||||
for (probenum = 0; probenum < listsz && !goodone; probenum++) {
|
||||
|
|
@ -1755,26 +1770,26 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
if (!probe->isPing()) {
|
||||
/* Now that response has been matched to a probe, I interpret it */
|
||||
if (USI->scantype == SCTP_INIT_SCAN) {
|
||||
if (chunk->sch_type == SCTP_INIT_ACK) {
|
||||
if (chunk.sch_type == SCTP_INIT_ACK) {
|
||||
newstate = PORT_OPEN;
|
||||
current_reason = ER_INITACK;
|
||||
} else if (chunk->sch_type == SCTP_ABORT) {
|
||||
} else if (chunk.sch_type == SCTP_ABORT) {
|
||||
newstate = PORT_CLOSED;
|
||||
current_reason = ER_ABORT;
|
||||
} else {
|
||||
if (o.debugging)
|
||||
error("Received response with unexpected SCTP chunks: %02x",
|
||||
chunk->sch_type);
|
||||
chunk.sch_type);
|
||||
break;
|
||||
}
|
||||
} else if (USI->scantype == SCTP_COOKIE_ECHO_SCAN) {
|
||||
if (chunk->sch_type == SCTP_ABORT) {
|
||||
if (chunk.sch_type == SCTP_ABORT) {
|
||||
newstate = PORT_CLOSED;
|
||||
current_reason = ER_ABORT;
|
||||
} else {
|
||||
if (o.debugging)
|
||||
error("Received response with unexpected SCTP chunks: %02x",
|
||||
chunk->sch_type);
|
||||
chunk.sch_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1786,13 +1801,12 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
const void *encaps_data;
|
||||
unsigned int encaps_len;
|
||||
struct abstract_ip_hdr encaps_hdr;
|
||||
const struct icmp *icmp = NULL;
|
||||
|
||||
icmp = (struct icmp *) data;
|
||||
struct icmp icmp;
|
||||
memcpy(&icmp, data, sizeof(icmp));
|
||||
|
||||
if (datalen < 8)
|
||||
continue;
|
||||
if (icmp->icmp_type != 3 && icmp->icmp_type != 11)
|
||||
if (icmp.icmp_type != 3 && icmp.icmp_type != 11)
|
||||
continue;
|
||||
|
||||
encaps_len = datalen - 8;
|
||||
|
|
@ -1840,29 +1854,32 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
continue;
|
||||
|
||||
if (encaps_hdr.proto == IPPROTO_TCP && !USI->prot_scan) {
|
||||
const struct tcp_hdr *tcp = (struct tcp_hdr *) encaps_data;
|
||||
if (ntohs(tcp->th_sport) != probe->sport() ||
|
||||
ntohs(tcp->th_dport) != probe->dport() ||
|
||||
ntohl(tcp->th_seq) != probe->tcpseq())
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, encaps_data, sizeof(tcp));
|
||||
if (ntohs(tcp.th_sport) != probe->sport() ||
|
||||
ntohs(tcp.th_dport) != probe->dport() ||
|
||||
ntohl(tcp.th_seq) != probe->tcpseq())
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_SCTP && !USI->prot_scan) {
|
||||
const struct sctp_hdr *sctp = (struct sctp_hdr *) encaps_data;
|
||||
if (ntohs(sctp->sh_sport) != probe->sport() ||
|
||||
ntohs(sctp->sh_dport) != probe->dport() ||
|
||||
ntohl(sctp->sh_vtag) != probe->sctpvtag())
|
||||
struct sctp_hdr sctp;
|
||||
memcpy(&sctp, encaps_data, sizeof(sctp));
|
||||
if (ntohs(sctp.sh_sport) != probe->sport() ||
|
||||
ntohs(sctp.sh_dport) != probe->dport() ||
|
||||
ntohl(sctp.sh_vtag) != probe->sctpvtag())
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_UDP && !USI->prot_scan) {
|
||||
/* TODO: IPID verification */
|
||||
const struct udp_hdr *udp = (struct udp_hdr *) encaps_data;
|
||||
if (ntohs(udp->uh_sport) != probe->sport() ||
|
||||
ntohs(udp->uh_dport) != probe->dport())
|
||||
struct udp_hdr udp;
|
||||
memcpy(&udp, encaps_data, sizeof(udp));
|
||||
if (ntohs(udp.uh_sport) != probe->sport() ||
|
||||
ntohs(udp.uh_dport) != probe->dport())
|
||||
continue;
|
||||
} else if (!USI->prot_scan) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (icmp->icmp_type == 3) {
|
||||
switch (icmp->icmp_code) {
|
||||
if (icmp.icmp_type == 3) {
|
||||
switch (icmp.icmp_code) {
|
||||
case 0: /* Network unreachable */
|
||||
newstate = PORT_FILTERED;
|
||||
break;
|
||||
|
|
@ -1891,18 +1908,18 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
|
||||
default:
|
||||
error("Unexpected ICMP type/code 3/%d unreachable packet:\n",
|
||||
icmp->icmp_code);
|
||||
nmap_hexdump((unsigned char *)icmp, datalen);
|
||||
icmp.icmp_code);
|
||||
nmap_hexdump((const u8*)data, datalen);
|
||||
break;
|
||||
}
|
||||
current_reason = icmp_to_reason(hdr.proto, icmp->icmp_type, icmp->icmp_code);
|
||||
current_reason = icmp_to_reason(hdr.proto, icmp.icmp_type, icmp.icmp_code);
|
||||
if (newstate == PORT_UNKNOWN)
|
||||
break;
|
||||
goodone = true;
|
||||
}
|
||||
else if (icmp->icmp_type == 11) { /* ICMP Time Exceeded */
|
||||
else if (icmp.icmp_type == 11) { /* ICMP Time Exceeded */
|
||||
newstate = PORT_FILTERED;
|
||||
current_reason = icmp_to_reason(hdr.proto, icmp->icmp_type, icmp->icmp_code);
|
||||
current_reason = icmp_to_reason(hdr.proto, icmp.icmp_type, icmp.icmp_code);
|
||||
goodone = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1910,13 +1927,14 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
const void *encaps_data;
|
||||
unsigned int encaps_len;
|
||||
struct abstract_ip_hdr encaps_hdr;
|
||||
const struct icmpv6_hdr *icmpv6;
|
||||
|
||||
icmpv6 = (struct icmpv6_hdr *) data;
|
||||
|
||||
if (datalen < 8)
|
||||
continue;
|
||||
if (!(icmpv6->icmpv6_type == ICMPV6_UNREACH || icmpv6->icmpv6_type == ICMPV6_PARAMPROBLEM))
|
||||
|
||||
struct icmpv6_hdr icmpv6;
|
||||
memcpy(&icmpv6, data, sizeof(icmpv6));
|
||||
|
||||
if (!(icmpv6.icmpv6_type == ICMPV6_UNREACH || icmpv6.icmpv6_type == ICMPV6_PARAMPROBLEM))
|
||||
continue;
|
||||
|
||||
encaps_len = datalen - 8;
|
||||
|
|
@ -1964,29 +1982,32 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
continue;
|
||||
|
||||
if (encaps_hdr.proto == IPPROTO_TCP && !USI->prot_scan) {
|
||||
const struct tcp_hdr *tcp = (struct tcp_hdr *) encaps_data;
|
||||
if (ntohs(tcp->th_sport) != probe->sport() ||
|
||||
ntohs(tcp->th_dport) != probe->dport() ||
|
||||
ntohl(tcp->th_seq) != probe->tcpseq())
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, encaps_data, sizeof(tcp));
|
||||
if (ntohs(tcp.th_sport) != probe->sport() ||
|
||||
ntohs(tcp.th_dport) != probe->dport() ||
|
||||
ntohl(tcp.th_seq) != probe->tcpseq())
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_SCTP && !USI->prot_scan) {
|
||||
const struct sctp_hdr *sctp = (struct sctp_hdr *) encaps_data;
|
||||
if (ntohs(sctp->sh_sport) != probe->sport() ||
|
||||
ntohs(sctp->sh_dport) != probe->dport() ||
|
||||
ntohl(sctp->sh_vtag) != probe->sctpvtag())
|
||||
struct sctp_hdr sctp;
|
||||
memcpy(&sctp, encaps_data, sizeof(sctp));
|
||||
if (ntohs(sctp.sh_sport) != probe->sport() ||
|
||||
ntohs(sctp.sh_dport) != probe->dport() ||
|
||||
ntohl(sctp.sh_vtag) != probe->sctpvtag())
|
||||
continue;
|
||||
} else if (encaps_hdr.proto == IPPROTO_UDP && !USI->prot_scan) {
|
||||
/* TODO: IPID verification */
|
||||
const struct udp_hdr *udp = (struct udp_hdr *) encaps_data;
|
||||
if (ntohs(udp->uh_sport) != probe->sport() ||
|
||||
ntohs(udp->uh_dport) != probe->dport())
|
||||
struct udp_hdr udp;
|
||||
memcpy(&udp, encaps_data, sizeof(udp));
|
||||
if (ntohs(udp.uh_sport) != probe->sport() ||
|
||||
ntohs(udp.uh_dport) != probe->dport())
|
||||
continue;
|
||||
} else if (!USI->prot_scan) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (icmpv6->icmpv6_type == ICMPV6_UNREACH) {
|
||||
switch (icmpv6->icmpv6_code) {
|
||||
if (icmpv6.icmpv6_type == ICMPV6_UNREACH) {
|
||||
switch (icmpv6.icmpv6_code) {
|
||||
case ICMPV6_UNREACH_NOROUTE:
|
||||
current_reason = ER_NOROUTE;
|
||||
newstate = PORT_FILTERED;
|
||||
|
|
@ -2022,12 +2043,12 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
break;
|
||||
default:
|
||||
error("Unexpected ICMPv6 type/code %d/%d unreachable packet:\n",
|
||||
icmpv6->icmpv6_type, icmpv6->icmpv6_code);
|
||||
nmap_hexdump((unsigned char *)icmpv6, datalen);
|
||||
icmpv6.icmpv6_type, icmpv6.icmpv6_code);
|
||||
nmap_hexdump((unsigned char *)data, datalen);
|
||||
break;
|
||||
}
|
||||
} else if (icmpv6->icmpv6_type == ICMPV6_PARAMPROBLEM) {
|
||||
switch (icmpv6->icmpv6_code) {
|
||||
} else if (icmpv6.icmpv6_type == ICMPV6_PARAMPROBLEM) {
|
||||
switch (icmpv6.icmpv6_code) {
|
||||
case ICMPV6_PARAMPROBLEM_FIELD:
|
||||
/* "Erroneous header field encountered" means it was understood,
|
||||
just invalid. */
|
||||
|
|
@ -2041,23 +2062,22 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
break;
|
||||
default:
|
||||
error("Unexpected ICMPv6 type/code %d/%d unreachable packet:\n",
|
||||
icmpv6->icmpv6_type, icmpv6->icmpv6_code);
|
||||
nmap_hexdump((unsigned char *)icmpv6, datalen);
|
||||
icmpv6.icmpv6_type, icmpv6.icmpv6_code);
|
||||
nmap_hexdump((unsigned char *)data, datalen);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error("Unexpected ICMPv6 type/code %d/%d unreachable packet:\n",
|
||||
icmpv6->icmpv6_type, icmpv6->icmpv6_code);
|
||||
nmap_hexdump((unsigned char *)icmpv6, datalen);
|
||||
icmpv6.icmpv6_type, icmpv6.icmpv6_code);
|
||||
nmap_hexdump((unsigned char *)data, datalen);
|
||||
break;
|
||||
}
|
||||
current_reason = icmp_to_reason(hdr.proto, icmpv6->icmpv6_type, icmpv6->icmpv6_code);
|
||||
current_reason = icmp_to_reason(hdr.proto, icmpv6.icmpv6_type, icmpv6.icmpv6_code);
|
||||
if (newstate == PORT_UNKNOWN)
|
||||
break;
|
||||
goodone = true;
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_UDP && !USI->prot_scan) {
|
||||
const struct udp_hdr *udp = (struct udp_hdr *) data;
|
||||
|
||||
/* Search for this host on the incomplete list */
|
||||
hss = USI->findHost(&hdr.src);
|
||||
|
|
@ -2065,8 +2085,12 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
continue; // Not from a host that interests us
|
||||
probeI = hss->probes_outstanding.end();
|
||||
listsz = hss->num_probes_outstanding();
|
||||
u16 sport = ntohs(udp->uh_sport);
|
||||
u16 dport = ntohs(udp->uh_dport);
|
||||
|
||||
struct udp_hdr udp;
|
||||
memcpy(&udp, data, sizeof(udp));
|
||||
|
||||
u16 sport = ntohs(udp.uh_sport);
|
||||
u16 dport = ntohs(udp.uh_dport);
|
||||
|
||||
goodone = false;
|
||||
|
||||
|
|
@ -2143,17 +2167,18 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
|
|||
if (probe->isPing())
|
||||
ultrascan_ping_update(USI, hss, probeI, &rcvdtime, adjust_timing);
|
||||
else {
|
||||
const struct icmp *icmp = (struct icmp *) data;
|
||||
struct icmp icmp;
|
||||
memcpy(&icmp, data, sizeof(icmp));
|
||||
ultrascan_port_probe_update(USI, hss, probeI, PORT_OPEN, &rcvdtime, adjust_timing);
|
||||
if (sockaddr_storage_cmp(&hdr.src, &protoscanicmphackaddy) == 0)
|
||||
reason_sip.ss_family = AF_UNSPEC;
|
||||
else
|
||||
reason_sip = hdr.src;
|
||||
if (!icmp->icmp_code && !icmp->icmp_type)
|
||||
if (!icmp.icmp_code && !icmp.icmp_type)
|
||||
hss->target->ports.setStateReason(IPPROTO_ICMP, IPPROTO_IP, ER_ECHOREPLY,
|
||||
hdr.ttl, &reason_sip);
|
||||
else
|
||||
hss->target->ports.setStateReason(IPPROTO_ICMP, IPPROTO_IP, icmp_to_reason(hdr.proto, icmp->icmp_type, icmp->icmp_code),
|
||||
hss->target->ports.setStateReason(IPPROTO_ICMP, IPPROTO_IP, icmp_to_reason(hdr.proto, icmp.icmp_type, icmp.icmp_code),
|
||||
hdr.ttl, &reason_sip);
|
||||
}
|
||||
if (!goodone)
|
||||
|
|
|
|||
67
tcpip.cc
67
tcpip.cc
|
|
@ -166,7 +166,7 @@ void PacketTrace::traceArp(pdirection pdir, const u8 *frame, u32 len,
|
|||
void PacketTrace::traceND(pdirection pdir, const u8 *frame, u32 len,
|
||||
struct timeval *now) {
|
||||
struct timeval tv;
|
||||
const struct ip6_hdr *ip6;
|
||||
struct ip6_hdr ip6;
|
||||
const struct icmpv6_hdr *icmpv6;
|
||||
const union icmpv6_msg *msg;
|
||||
size_t msg_len;
|
||||
|
|
@ -191,15 +191,15 @@ void PacketTrace::traceND(pdirection pdir, const u8 *frame, u32 len,
|
|||
else
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
if (len < sizeof(*ip6) + sizeof(*icmpv6)) {
|
||||
if (len < sizeof(ip6) + sizeof(*icmpv6)) {
|
||||
error("Packet tracer: ND packets must be at least %lu bytes long (is %lu).",
|
||||
(unsigned long) (sizeof(*ip6) + sizeof(*icmpv6)),
|
||||
(unsigned long) (sizeof(ip6) + sizeof(*icmpv6)),
|
||||
(unsigned long) len);
|
||||
return;
|
||||
}
|
||||
ip6 = (struct ip6_hdr *) frame;
|
||||
icmpv6 = (struct icmpv6_hdr *) (frame + sizeof(*ip6));
|
||||
msg = (union icmpv6_msg *) (frame + sizeof(*ip6) + sizeof(*icmpv6));
|
||||
memcpy(&ip6, frame, sizeof(ip6));
|
||||
icmpv6 = (struct icmpv6_hdr *) (frame + sizeof(ip6));
|
||||
msg = (union icmpv6_msg *) (frame + sizeof(ip6) + sizeof(*icmpv6));
|
||||
msg_len = frame + len - (u8 *) msg;
|
||||
|
||||
if (icmpv6->icmpv6_type == ICMPV6_NEIGHBOR_SOLICITATION) {
|
||||
|
|
@ -227,8 +227,8 @@ void PacketTrace::traceND(pdirection pdir, const u8 *frame, u32 len,
|
|||
return;
|
||||
}
|
||||
|
||||
inet_ntop(AF_INET6, (void *)&ip6->ip6_src, src, sizeof(src));
|
||||
inet_ntop(AF_INET6, (void *)&ip6->ip6_dst, dst, sizeof(dst));
|
||||
inet_ntop(AF_INET6, (void *)&ip6.ip6_src, src, sizeof(src));
|
||||
inet_ntop(AF_INET6, (void *)&ip6.ip6_dst, dst, sizeof(dst));
|
||||
log_write(LOG_STDOUT | LOG_NORMAL, "%s (%.4fs) %s %s > %s %s\n",
|
||||
(pdir == SENT) ? "SENT" : "RCVD",
|
||||
o.TimeSinceStart(&tv), label, src, dst, desc);
|
||||
|
|
@ -1266,10 +1266,13 @@ int readudppacket(const u8 *packet, int readdata) {
|
|||
/* Used by validatepkt() to validate the TCP header (including option lengths).
|
||||
The options checked are MSS, WScale, SackOK, Sack, and Timestamp. */
|
||||
static bool validateTCPhdr(const u8 *tcpc, unsigned len) {
|
||||
const struct tcp_hdr *tcp = (struct tcp_hdr *) tcpc;
|
||||
struct tcp_hdr tcp = {};
|
||||
if (len < sizeof(tcp))
|
||||
return false;
|
||||
memcpy(&tcp, tcpc, sizeof(tcp));
|
||||
unsigned hdrlen, optlen;
|
||||
|
||||
hdrlen = tcp->th_off * 4;
|
||||
hdrlen = tcp.th_off * 4;
|
||||
|
||||
/* Check header length */
|
||||
if (hdrlen > len || hdrlen < sizeof(struct tcp_hdr))
|
||||
|
|
@ -1354,7 +1357,8 @@ static bool validateTCPhdr(const u8 *tcpc, unsigned len) {
|
|||
* data to the caller.
|
||||
*/
|
||||
static bool validatepkt(const u8 *ipc, unsigned *len) {
|
||||
const struct ip *ip = (struct ip *) ipc;
|
||||
struct ip ip;
|
||||
memcpy(&ip, ipc, sizeof(ip));
|
||||
const void *data;
|
||||
unsigned int datalen, iplen;
|
||||
u8 hdr;
|
||||
|
|
@ -1365,20 +1369,20 @@ static bool validatepkt(const u8 *ipc, unsigned *len) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (ip->ip_v == 4) {
|
||||
if (ip.ip_v == 4) {
|
||||
unsigned fragoff, iplen;
|
||||
|
||||
datalen = *len;
|
||||
data = ipv4_get_data(ip, &datalen);
|
||||
data = ipv4_get_data(ipc, &datalen);
|
||||
if (data == NULL) {
|
||||
if (o.debugging >= 3)
|
||||
error("Rejecting IP packet because of invalid length");
|
||||
return false;
|
||||
}
|
||||
|
||||
iplen = ntohs(ip->ip_len);
|
||||
iplen = ntohs(ip.ip_len);
|
||||
|
||||
fragoff = 8 * (ntohs(ip->ip_off) & IP_OFFMASK);
|
||||
fragoff = 8 * (ntohs(ip.ip_off) & IP_OFFMASK);
|
||||
if (fragoff) {
|
||||
if (o.debugging >= 3)
|
||||
error("Rejecting IP fragment (offset %u)", fragoff);
|
||||
|
|
@ -1391,24 +1395,25 @@ static bool validatepkt(const u8 *ipc, unsigned *len) {
|
|||
if (*len > iplen)
|
||||
*len = iplen;
|
||||
|
||||
hdr = ip->ip_p;
|
||||
} else if (ip->ip_v == 6) {
|
||||
const struct ip6_hdr *ip6 = (struct ip6_hdr *) ipc;
|
||||
hdr = ip.ip_p;
|
||||
} else if (ip.ip_v == 6) {
|
||||
struct ip6_hdr ip6;
|
||||
memcpy(&ip6, ipc, sizeof(ip6));
|
||||
|
||||
datalen = *len;
|
||||
data = ipv6_get_data(ip6, &datalen, &hdr);
|
||||
data = ipv6_get_data(ipc, &datalen, &hdr);
|
||||
if (data == NULL) {
|
||||
if (o.debugging >= 3)
|
||||
error("Rejecting IP packet because of invalid length");
|
||||
return false;
|
||||
}
|
||||
|
||||
iplen = ntohs(ip6->ip6_plen);
|
||||
iplen = ntohs(ip6.ip6_plen);
|
||||
if (datalen > iplen)
|
||||
*len -= datalen - iplen;
|
||||
} else {
|
||||
if (o.debugging >= 3)
|
||||
error("Rejecting IP packet because of invalid version number %u", ip->ip_v);
|
||||
error("Rejecting IP packet because of invalid version number %u", ip.ip_v);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1460,10 +1465,7 @@ const u8 *readipv4_pcap(pcap_t *pd, unsigned int *len, long to_usec,
|
|||
|
||||
buf = readip_pcap(pd, len, to_usec, rcvdtime, linknfo, validate);
|
||||
if (buf != NULL) {
|
||||
const struct ip *ip;
|
||||
|
||||
ip = (struct ip *) buf;
|
||||
if (*len < 1 || ip->ip_v != 4)
|
||||
if (*len < 1 || (buf[0] >> 4) != 4)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1475,13 +1477,12 @@ static bool accept_any (const unsigned char *p, const struct pcap_pkthdr *h, int
|
|||
}
|
||||
|
||||
static bool accept_ip (const unsigned char *p, const struct pcap_pkthdr *h, int datalink, size_t offset) {
|
||||
const struct ip *ip = NULL;
|
||||
|
||||
if (h->caplen < offset + sizeof(struct ip)) {
|
||||
return false;
|
||||
}
|
||||
ip = (struct ip *) (p + offset);
|
||||
switch (ip->ip_v) {
|
||||
u8 v = p[offset] >> 4;
|
||||
switch (v) {
|
||||
case 4:
|
||||
case 6:
|
||||
break;
|
||||
|
|
@ -1766,16 +1767,18 @@ int recvtime(int sd, char *buf, int len, int seconds, int *timedout) {
|
|||
parameters (if non-null) are filled with 0. Remember that the
|
||||
correct way to check for errors is to look at the return value
|
||||
since a zero ts or echots could possibly be valid. */
|
||||
int gettcpopt_ts(const struct tcp_hdr *tcp, u32 *timestamp, u32 *echots) {
|
||||
int gettcpopt_ts(const u8 *tcppkt, u32 *timestamp, u32 *echots) {
|
||||
|
||||
unsigned char *p;
|
||||
const u8 *p;
|
||||
int len = 0;
|
||||
int op;
|
||||
int oplen;
|
||||
struct tcp_hdr tcp;
|
||||
memcpy(&tcp, tcppkt, sizeof(tcp));
|
||||
|
||||
/* first we find where the tcp options start ... */
|
||||
p = ((unsigned char *) tcp) + 20;
|
||||
len = 4 * tcp->th_off - 20;
|
||||
p = tcppkt + 20;
|
||||
len = 4 * tcp.th_off - 20;
|
||||
while (len > 0 && *p != 0 /* TCPOPT_EOL */ ) {
|
||||
op = *p++;
|
||||
if (op == 0 /* TCPOPT_EOL */ )
|
||||
|
|
|
|||
2
tcpip.h
2
tcpip.h
|
|
@ -368,7 +368,7 @@ const u8 *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec,
|
|||
parameters (if non-null) are filled with 0. Remember that the
|
||||
correct way to check for errors is to look at the return value
|
||||
since a zero ts or echots could possibly be valid. */
|
||||
int gettcpopt_ts(const struct tcp_hdr *tcp, u32 *timestamp, u32 *echots);
|
||||
int gettcpopt_ts(const u8 *tcppkt, u32 *timestamp, u32 *echots);
|
||||
|
||||
/* Maximize the receive buffer of a socket descriptor (up to 500K) */
|
||||
void max_rcvbuf(int sd);
|
||||
|
|
|
|||
117
traceroute.cc
117
traceroute.cc
|
|
@ -1068,6 +1068,10 @@ struct Reply {
|
|||
u16 token;
|
||||
};
|
||||
|
||||
#define ALIGN_HEADER(_Type, _Name, _Ptr, _Offset, _Len) \
|
||||
_Type _Name; \
|
||||
memcpy(&_Name, (u8 *)_Ptr + _Offset, MIN(_Len - _Offset, sizeof(_Type)));
|
||||
|
||||
static bool parse_encapsulated_reply(const void *ip, unsigned len, Reply *reply) {
|
||||
struct abstract_ip_hdr hdr;
|
||||
const void *data;
|
||||
|
|
@ -1077,30 +1081,31 @@ static bool parse_encapsulated_reply(const void *ip, unsigned len, Reply *reply)
|
|||
return false;
|
||||
|
||||
if (hdr.version == 4 && hdr.proto == IPPROTO_ICMP) {
|
||||
const struct icmp *icmp = (const struct icmp *) data;
|
||||
if (len < 8 || ntohs(icmp->icmp_id) != global_id)
|
||||
if (len < offsetof(struct icmp, icmp_id) + 2)
|
||||
return false;
|
||||
reply->token = ntohs(icmp->icmp_seq);
|
||||
ALIGN_HEADER(struct icmp, icmp, data, 0, len);
|
||||
if (ntohs(icmp.icmp_id) != global_id)
|
||||
return false;
|
||||
reply->token = ntohs(icmp.icmp_seq);
|
||||
} else if (hdr.version == 6 && hdr.proto == IPPROTO_ICMPV6) {
|
||||
const struct icmpv6_msg_echo *echo = (struct icmpv6_msg_echo *) ((char *) data + sizeof(struct icmpv6_hdr));
|
||||
if (len < 8 || ntohs(echo->icmpv6_id) != global_id)
|
||||
if (len < sizeof(struct icmpv6_hdr) + offsetof(struct icmpv6_msg_echo, icmpv6_seq) + 2)
|
||||
return false;
|
||||
reply->token = ntohs(echo->icmpv6_seq);
|
||||
ALIGN_HEADER(struct icmpv6_msg_echo, echo, data, sizeof(struct icmpv6_hdr), len);
|
||||
if (ntohs(echo.icmpv6_id) != global_id)
|
||||
return false;
|
||||
reply->token = ntohs(echo.icmpv6_seq);
|
||||
} else if (hdr.proto == IPPROTO_TCP) {
|
||||
const struct tcp_hdr *tcp = (const struct tcp_hdr *) data;
|
||||
if (len < 2)
|
||||
return false;
|
||||
reply->token = ntohs(tcp->th_sport) ^ global_id;
|
||||
if (len < offsetof(struct tcp_hdr, th_sport) + 2) return false;
|
||||
ALIGN_HEADER(struct tcp_hdr, tcp, data, 0, len);
|
||||
reply->token = ntohs(tcp.th_sport) ^ global_id;
|
||||
} else if (hdr.proto == IPPROTO_UDP) {
|
||||
const struct udp_hdr *udp = (const struct udp_hdr *) data;
|
||||
if (len < 2)
|
||||
return false;
|
||||
reply->token = ntohs(udp->uh_sport) ^ global_id;
|
||||
if (len < offsetof(struct udp_hdr, uh_sport) + 2) return false;
|
||||
ALIGN_HEADER(struct udp_hdr, udp, data, 0, len);
|
||||
reply->token = ntohs(udp.uh_sport) ^ global_id;
|
||||
} else if (hdr.proto == IPPROTO_SCTP) {
|
||||
const struct sctp_hdr *sctp = (const struct sctp_hdr *) data;
|
||||
if (len < 2)
|
||||
return false;
|
||||
reply->token = ntohs(sctp->sh_sport) ^ global_id;
|
||||
if (len < offsetof(struct sctp_hdr, sh_sport) + 2) return false;
|
||||
ALIGN_HEADER(struct sctp_hdr, sctp, data, 0, len);
|
||||
reply->token = ntohs(sctp.sh_sport) ^ global_id;
|
||||
} else {
|
||||
if (len < 6)
|
||||
return false;
|
||||
|
|
@ -1127,26 +1132,24 @@ static bool decode_reply(const void *ip, unsigned int len, Reply *reply) {
|
|||
if (hdr.version == 4 && hdr.proto == IPPROTO_ICMP) {
|
||||
/* ICMP responses comprise all the TTL exceeded messages we expect from all
|
||||
probe types, as well as actual replies from ICMP probes. */
|
||||
const struct icmp_hdr *icmp = (const struct icmp_hdr *) data;
|
||||
if (len < 8)
|
||||
return false;
|
||||
if ((icmp->icmp_type == ICMP_TIMEXCEED
|
||||
&& icmp->icmp_code == ICMP_TIMEXCEED_INTRANS)
|
||||
|| icmp->icmp_type == ICMP_UNREACH) {
|
||||
ALIGN_HEADER(struct icmp_hdr, icmp, data, 0, len);
|
||||
if ((icmp.icmp_type == ICMP_TIMEXCEED
|
||||
&& icmp.icmp_code == ICMP_TIMEXCEED_INTRANS)
|
||||
|| icmp.icmp_type == ICMP_UNREACH) {
|
||||
/* Get the encapsulated IP packet. */
|
||||
const void *encaps = icmp_get_data(icmp, &len);
|
||||
const void *encaps = icmp_get_data(data, &len);
|
||||
if (encaps == NULL)
|
||||
return false;
|
||||
return parse_encapsulated_reply(encaps, len, reply);
|
||||
} else if (icmp->icmp_type == ICMP_ECHOREPLY
|
||||
|| icmp->icmp_type == ICMP_MASKREPLY
|
||||
|| icmp->icmp_type == ICMP_TSTAMPREPLY) {
|
||||
} else if (icmp.icmp_type == ICMP_ECHOREPLY
|
||||
|| icmp.icmp_type == ICMP_MASKREPLY
|
||||
|| icmp.icmp_type == ICMP_TSTAMPREPLY) {
|
||||
/* Need this alternate form of header for icmp_id and icmp_seq. */
|
||||
const struct icmp *icmp = (const struct icmp *) data;
|
||||
ALIGN_HEADER(struct icmp, icmp, data, 0, len);
|
||||
|
||||
if (ntohs(icmp->icmp_id) != global_id)
|
||||
if (ntohs(icmp.icmp_id) != global_id)
|
||||
return false;
|
||||
reply->token = ntohs(icmp->icmp_seq);
|
||||
reply->token = ntohs(icmp.icmp_seq);
|
||||
/* Reply came directly from the target. */
|
||||
reply->target_addr = reply->from_addr;
|
||||
} else {
|
||||
|
|
@ -1155,50 +1158,39 @@ static bool decode_reply(const void *ip, unsigned int len, Reply *reply) {
|
|||
} else if (hdr.version == 6 && hdr.proto == IP_PROTO_ICMPV6) {
|
||||
/* ICMPv6 responses comprise all the TTL exceeded messages we expect from
|
||||
all probe types, as well as actual replies from ICMP probes. */
|
||||
const struct icmpv6_hdr *icmpv6 = (const struct icmpv6_hdr *) data;
|
||||
if (len < 2)
|
||||
return false;
|
||||
ALIGN_HEADER(struct icmpv6_hdr, icmpv6, data, 0, len);
|
||||
/* TIMEXCEED, UNREACH */
|
||||
if ((icmpv6->icmpv6_type == ICMPV6_TIMEXCEED
|
||||
&& icmpv6->icmpv6_code == ICMPV6_TIMEXCEED_INTRANS)
|
||||
|| icmpv6->icmpv6_type == ICMPV6_UNREACH) {
|
||||
if ((icmpv6.icmpv6_type == ICMPV6_TIMEXCEED
|
||||
&& icmpv6.icmpv6_code == ICMPV6_TIMEXCEED_INTRANS)
|
||||
|| icmpv6.icmpv6_type == ICMPV6_UNREACH) {
|
||||
/* Get the encapsulated IP packet. */
|
||||
const void *encaps = icmpv6_get_data(icmpv6, &len);
|
||||
const void *encaps = icmpv6_get_data(data, &len);
|
||||
if (encaps == NULL)
|
||||
return false;
|
||||
return parse_encapsulated_reply(encaps, len, reply);
|
||||
} else if (icmpv6->icmpv6_type == ICMPV6_ECHOREPLY) {
|
||||
} else if (icmpv6.icmpv6_type == ICMPV6_ECHOREPLY) {
|
||||
/* MASKREPLY, TSTAMPREPLY */
|
||||
const struct icmpv6_msg_echo *echo;
|
||||
ALIGN_HEADER(struct icmpv6_msg_echo, echo, data, sizeof(icmpv6), len);
|
||||
|
||||
if (len < sizeof(*icmpv6) + 4)
|
||||
if (ntohs(echo.icmpv6_id) != global_id)
|
||||
return false;
|
||||
echo = (struct icmpv6_msg_echo *) ((char *) icmpv6 + sizeof(*icmpv6));
|
||||
if (ntohs(echo->icmpv6_id) != global_id)
|
||||
return false;
|
||||
reply->token = ntohs(echo->icmpv6_seq);
|
||||
reply->token = ntohs(echo.icmpv6_seq);
|
||||
/* Reply came directly from the target. */
|
||||
reply->target_addr = reply->from_addr;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (hdr.proto == IPPROTO_TCP) {
|
||||
const struct tcp_hdr *tcp = (const struct tcp_hdr *) data;
|
||||
if (len < 4)
|
||||
return false;
|
||||
reply->token = ntohs(tcp->th_dport) ^ global_id;
|
||||
ALIGN_HEADER(struct tcp_hdr, tcp, data, 0, len);
|
||||
reply->token = ntohs(tcp.th_dport) ^ global_id;
|
||||
reply->target_addr = reply->from_addr;
|
||||
} else if (hdr.proto == IPPROTO_UDP) {
|
||||
const struct udp_hdr *udp = (const struct udp_hdr *) data;
|
||||
if (len < 4)
|
||||
return false;
|
||||
reply->token = ntohs(udp->uh_dport) ^ global_id;
|
||||
ALIGN_HEADER(struct udp_hdr, udp, data, 0, len);
|
||||
reply->token = ntohs(udp.uh_dport) ^ global_id;
|
||||
reply->target_addr = reply->from_addr;
|
||||
} else if (hdr.proto == IPPROTO_SCTP) {
|
||||
const struct sctp_hdr *sctp = (const struct sctp_hdr *) data;
|
||||
if (len < 4)
|
||||
return false;
|
||||
reply->token = ntohs(sctp->sh_dport) ^ global_id;
|
||||
ALIGN_HEADER(struct sctp_hdr, sctp, data, 0, len);
|
||||
reply->token = ntohs(sctp.sh_dport) ^ global_id;
|
||||
reply->target_addr = reply->from_addr;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -1208,17 +1200,14 @@ static bool decode_reply(const void *ip, unsigned int len, Reply *reply) {
|
|||
}
|
||||
|
||||
static bool read_reply(Reply *reply, pcap_t *pd, long timeout) {
|
||||
const struct ip *ip;
|
||||
const void *ip;
|
||||
unsigned int iplen;
|
||||
struct link_header linkhdr;
|
||||
|
||||
ip = (struct ip *) readip_pcap(pd, &iplen, timeout, &reply->rcvdtime, &linkhdr, true);
|
||||
if (ip == NULL)
|
||||
return false;
|
||||
if (ip->ip_v == 4 || ip->ip_v == 6)
|
||||
ip = readip_pcap(pd, &iplen, timeout, &reply->rcvdtime, &linkhdr, true);
|
||||
if (ip)
|
||||
return decode_reply(ip, iplen, reply);
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void TracerouteState::read_replies(long timeout) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue