diff --git a/idle_scan.cc b/idle_scan.cc index 103d6fb04..84ef09e3f 100644 --- a/idle_scan.cc +++ b/idle_scan.cc @@ -136,19 +136,20 @@ struct idle_proxy_info { /* Finds the IPv6 extension header for fragmentation in an IPv6 packet, and returns * the identification value of the fragmentation header */ -int ipv6_get_fragment_id(const struct ip6_hdr *ip6, unsigned int len) { - const unsigned char *p, *end; +int ipv6_get_fragment_id(const u8 *pkt, unsigned int len) { + const u8 *p, *end; u8 hdr; - struct ip6_ext_data_fragment *frag_header = NULL; - if (len < sizeof(*ip6)) + struct ip6_hdr ip6; + if (len < sizeof(ip6)) return -1; + memcpy(&ip6, pkt, sizeof(ip6)); - p = (unsigned char *) ip6; + p = pkt; end = p + len; - hdr = ip6->ip6_nxt; - p += sizeof(*ip6); + hdr = ip6.ip6_nxt; + p += sizeof(ip6); /* If the first extension header is not the fragmentation, we search our way * through the extension headers until we find the fragmentation header */ @@ -162,9 +163,10 @@ int ipv6_get_fragment_id(const struct ip6_hdr *ip6, unsigned int len) { if (hdr != IP_PROTO_FRAGMENT || (p + 2 + sizeof(ip6_ext_data_fragment)) > end) return -1; - frag_header = (struct ip6_ext_data_fragment *)( p + 2 ); + struct ip6_ext_data_fragment frag_header; + memcpy(&frag_header, p + 2, sizeof(frag_header)); - return (ntohl(frag_header->ident)); + return (ntohl(frag_header.ident)); } @@ -183,19 +185,13 @@ static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent, struct timeval tv_sent[3], rcvdtime; int ipid = -1; int to_usec; - unsigned int bytes; int base_port; - struct ip *ip; - struct tcp_hdr *tcp = NULL; static u32 seq_base = 0; static u32 ack = 0; static int packet_send_count = 0; /* Total # of probes sent by this program -- to ensure that our sequence # always changes */ u32 packetlen = 0; u8 *ipv6_packet = NULL; const struct sockaddr_storage *ss; - struct ip6_hdr *ip6 = NULL; - const void *ipv6_data; - u8 hdr; int res; if (o.magic_port_set) @@ -248,56 +244,53 @@ static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent, to_usec = proxy->host.to.timeout - TIMEVAL_SUBTRACT(tv_end, tv_sent[tries - 1]); if (to_usec < 0) to_usec = 0; // Final no-block poll - ip = (struct ip *) readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + unsigned int bytes = 0; + const u8 *pkt = readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); gettimeofday(&tv_end, NULL); - if (ip) { - if (o.af() == AF_INET) { - if (bytes < (4 * ip->ip_hl) + 14U) - continue; - if (ip->ip_p == IPPROTO_TCP) - tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); - } else if (o.af() == AF_INET6) { - if (ip->ip_v != 6) { - error("IPv6 packet with a version field != 6 received"); - } else { - ip6 = (struct ip6_hdr *) ip; - ipv6_data = ipv6_get_data(ip6, &packetlen, &hdr); - if (hdr == IPPROTO_TCP && ipv6_data != NULL) { - tcp = (struct tcp_hdr *) ipv6_data; - } - } - } - if (tcp) { - if (ntohs(tcp->th_dport) < base_port || ntohs(tcp->th_dport) - base_port >= tries || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) { - if (ntohs(tcp->th_dport) > o.magic_port && ntohs(tcp->th_dport) < (o.magic_port + 260)) { - if (o.debugging) { - error("Received IP ID zombie probe response which probably came from an earlier prober instance ... increasing rttvar from %d to %d", - proxy->host.to.rttvar, (int) (proxy->host.to.rttvar * 1.2)); - } - proxy->host.to.rttvar = (int) (proxy->host.to.rttvar * 1.2); - rcvd++; - } else if (o.debugging > 1) { - char straddr[INET6_ADDRSTRLEN]; - if (o.af() == AF_INET) - inet_ntop(AF_INET, &(ip->ip_src), straddr, sizeof(straddr)); - else if (o.af() == AF_INET6) - inet_ntop(AF_INET6, &(ip6->ip6_src), straddr, sizeof(straddr)); - error("Received unexpected response packet from %s during IP ID zombie probing:", straddr); - readtcppacket((unsigned char *) ip, MIN(ntohs(ip->ip_len), bytes)); - } - continue; - } - - trynum = ntohs(tcp->th_dport) - base_port; - rcvd++; - - if (o.af() == AF_INET) - ipid = ntohs(ip->ip_id); - else if (o.af() == AF_INET6) - ipid = ipv6_get_fragment_id(ip6, bytes); - adjust_timeouts2(&(tv_sent[trynum]), &rcvdtime, &(proxy->host.to)); - } + if (!pkt || bytes < 20) { + continue; } + struct abstract_ip_hdr hdr; + + unsigned int tcpbytes = bytes; + const u8 *tcppkt = ip_get_data(pkt, &tcpbytes, &hdr); + if (!tcppkt || hdr.proto != IPPROTO_TCP) { + continue; + } + + if ((o.af() == AF_INET && hdr.version != 4) || + (o.af() == AF_INET6 && hdr.version != 6)) { + continue; + } + struct tcp_hdr tcp; + if (tcpbytes < sizeof(tcp)) + continue; + memcpy(&tcp, tcppkt, sizeof(tcp)); + + if (ntohs(tcp.th_dport) < base_port || ntohs(tcp.th_dport) - base_port >= tries || ntohs(tcp.th_sport) != proxy->probe_port || ((tcp.th_flags & TH_RST) == 0)) { + if (ntohs(tcp.th_dport) > o.magic_port && ntohs(tcp.th_dport) < (o.magic_port + 260)) { + if (o.debugging) { + error("Received IP ID zombie probe response which probably came from an earlier prober instance ... increasing rttvar from %d to %d", + proxy->host.to.rttvar, (int) (proxy->host.to.rttvar * 1.2)); + } + proxy->host.to.rttvar = (int) (proxy->host.to.rttvar * 1.2); + rcvd++; + } else if (o.debugging > 1) { + error("Received unexpected response packet from %s during IP ID zombie probing:", + inet_socktop(&hdr.src)); + readtcppacket(pkt, 0); + } + continue; + } + + trynum = ntohs(tcp.th_dport) - base_port; + rcvd++; + + if (o.af() == AF_INET) + ipid = hdr.ipid; + else if (o.af() == AF_INET6) + ipid = ipv6_get_fragment_id(pkt, bytes); + adjust_timeouts2(&(tv_sent[trynum]), &rcvdtime, &(proxy->host.to)); } } while (ipid == -1 && tries < maxtries); @@ -354,7 +347,7 @@ static void initialize_proxy_struct(struct idle_proxy_info *proxy) { static void ipv6_force_fragmentation(struct idle_proxy_info *proxy, Target *target) { int hardtimeout = 9000000; /* Generally don't wait more than 9 secs total */ char filter[512]; /* Libpcap filter string */ - struct ip *ip; + const u8 *pkt; /* The maximum data size we can create without fragmenting, considering that the headers also need place */ char data[IP6_MTU_MIN - IPv6_HEADER_LEN - ETH_HDR_LEN - ICMPv6_MIN_HEADER_LEN]; unsigned int datalen, bytes; @@ -398,8 +391,8 @@ static void ipv6_force_fragmentation(struct idle_proxy_info *proxy, Target *targ /* Now let's wait for the answer */ while (!response_received) { gettimeofday(&tmptv, NULL); - ip = (struct ip *) readip_pcap(proxy->pd, &bytes, proxy_reply_timeout, &rcvdtime, NULL, true); - if (!ip) { + pkt = readip_pcap(proxy->pd, &bytes, proxy_reply_timeout, &rcvdtime, NULL, true); + if (!pkt) { if (TIMEVAL_SUBTRACT(tmptv, ipv6_packet_send_time) >= hardtimeout) { fatal("Idle scan zombie %s (%s) port %hu cannot be used because it has not returned any of our ICMPv6 Echo Requests -- perhaps it is down or firewalled.", proxy->host.HostName(), proxy->host.targetipstr(), @@ -408,7 +401,7 @@ static void ipv6_force_fragmentation(struct idle_proxy_info *proxy, Target *targ continue; } datalen = bytes; - rdata = ip_get_data(ip, &datalen, &hdr); + rdata = ip_get_data(pkt, &datalen, &hdr); if (hdr.version == 6 && hdr.proto == IPPROTO_ICMPV6) { icmp6_header = (struct icmpv6_hdr *) rdata; if (icmp6_header->icmpv6_type == ICMPV6_ECHOREPLY) { @@ -426,7 +419,7 @@ static void ipv6_force_fragmentation(struct idle_proxy_info *proxy, Target *targ /* Now we can tell the idle host that its reply was too big, we want it smaller than the IPV6 minimum MTU */ /* the data contains first the MTU we want, and then the received IPv6 package */ *(uint32_t *)&data = ntohl(IP6_MTU_MIN - 2); - memcpy(&data[4], ip, sizeof(data)-4); + memcpy(&data[4], pkt, sizeof(data)-4); ipv6_packet = build_icmpv6_raw(proxy->host.v6sourceip(), proxy->host.v6hostip(), 0x00, 0x0000, o.ttl, 0x00 , 0x00, 0x02, 0x00, data, sizeof(data) , &packetlen); res = send_ip_packet(proxy->rawsd, proxy->ethptr, ss, ipv6_packet, packetlen); @@ -487,8 +480,6 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, u32 ack = 0; struct timeval probe_send_times[NUM_IPID_PROBES], tmptv, rcvdtime; u32 lastipid = 0; - struct ip *ip; - struct tcp_hdr *tcp; int distance; u32 ipids[NUM_IPID_PROBES]; u8 probe_returned[NUM_IPID_PROBES]; @@ -496,7 +487,6 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, assert(proxyName); u8 *ipv6_packet = NULL; u32 packetlen = 0; - const struct ip6_hdr *ip6; u8 ip6hdr; const void *ip6data; bool retried_forcing_fragmentation = false; @@ -680,11 +670,11 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, while (probes_returned < probes_sent && !timedout) { to_usec = (probes_sent == NUM_IPID_PROBES) ? hardtimeout : 1000; - ip = (struct ip *) readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + const u8 *pkt = readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); gettimeofday(&tmptv, NULL); - if (!ip) { + if (!pkt || bytes < 20) { if (probes_sent < NUM_IPID_PROBES) break; if (TIMEVAL_SUBTRACT(tmptv, probe_send_times[probes_sent - 1]) >= hardtimeout) { @@ -695,28 +685,37 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, timedout = 1; } + u8 ip_v = pkt[0] >> 4; + if (o.af() == AF_INET) { - if (ip->ip_v != 4) { + if (ip_v != 4) { error("Received a packet with version field != 4"); continue; } - if (lastipid != 0 && ip->ip_id == lastipid) { + + struct ip ip; + if (bytes < sizeof(ip)) + continue; + memcpy(&ip, pkt, sizeof(ip)); + + if (lastipid != 0 && ip.ip_id == lastipid) { continue; /* probably a duplicate */ } - lastipid = ip->ip_id; - if (bytes < (4 * ip->ip_hl) + 14U) + lastipid = ip.ip_id; + if (bytes < (4 * ip.ip_hl) + 14U) continue; - if (ip->ip_p == IPPROTO_TCP) { - tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); + if (ip.ip_p == IPPROTO_TCP) { + struct tcp_hdr tcp; + memcpy(&tcp, pkt + 4 * ip.ip_hl, sizeof(tcp)); /* Checking now for the source port, which we were not able to do in the libpcap filter */ - if (ntohs(tcp->th_sport) != proxy->probe_port) { + if (ntohs(tcp.th_sport) != proxy->probe_port) { continue; } - if (ntohs(tcp->th_dport) < (o.magic_port + 1) || ntohs(tcp->th_dport) - o.magic_port > NUM_IPID_PROBES || ((tcp->th_flags & TH_RST) == 0)) { + if (ntohs(tcp.th_dport) < (o.magic_port + 1) || ntohs(tcp.th_dport) - o.magic_port > NUM_IPID_PROBES || ((tcp.th_flags & TH_RST) == 0)) { if (o.debugging > 1) - error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip->ip_src)); + error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip.ip_src)); continue; } @@ -727,17 +726,19 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, of sneaking through the firewall. Plus SYN|ACK is what they will be receiving back from the target */ probes_returned++; - ipids[seq_response_num] = ntohs(ip->ip_id); + ipids[seq_response_num] = ntohs(ip.ip_id); probe_returned[seq_response_num] = 1; adjust_timeouts2(&probe_send_times[seq_response_num], &rcvdtime, &(proxy->host.to)); } } else if (o.af() == AF_INET6) { - if (ip->ip_v != 6) { + if (ip_v != 6) { error("Received a packet with version field != 6"); continue; } else { - ip6 = (struct ip6_hdr *) ip; - newipid = ipv6_get_fragment_id(ip6, bytes); + struct ip6_hdr ip6; + if (bytes < sizeof(ip6)) + continue; + newipid = ipv6_get_fragment_id(pkt, bytes); if (newipid < 0 ) { /* ok, the idle host does not seem to append the extension header for fragmentation. Let's try this once more, * maybe the idle host just adjusted its Path MTU. If we keep on having the problem, we quit */ @@ -753,22 +754,27 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, } lastipid = newipid; - ip6data = ipv6_get_data(ip6, &packetlen, &ip6hdr); - if (ip6hdr == IPPROTO_TCP && ip6data != NULL) { - tcp = (struct tcp_hdr *) ip6data; - /* Checking now for the source port, which we were not able to do in the libpcap filter */ - if (ntohs(tcp->th_sport) != proxy->probe_port) { - continue; - } - }else - { + ip6data = ipv6_get_data(pkt, &packetlen, &ip6hdr); + if (ip6data == NULL || ip6hdr != IPPROTO_TCP) { error("Malformed packet received"); continue; } - if (ntohs(tcp->th_dport) < (o.magic_port + 1) || ntohs(tcp->th_dport) - o.magic_port > NUM_IPID_PROBES || ((tcp->th_flags & TH_RST) == 0)) { - if (o.debugging > 1) - error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip->ip_src)); + struct tcp_hdr tcp; + if (packetlen < sizeof(tcp)) { + continue; + } + memcpy(&tcp, ip6data, sizeof(tcp)); + /* Checking now for the source port, which we were not able to do in the libpcap filter */ + if (ntohs(tcp.th_sport) != proxy->probe_port) { + continue; + } + + if (ntohs(tcp.th_dport) < (o.magic_port + 1) || ntohs(tcp.th_dport) - o.magic_port > NUM_IPID_PROBES || ((tcp.th_flags & TH_RST) == 0)) { + if (o.debugging > 1) { + memcpy(&ip6, pkt, sizeof(ip6)); + error("Received unexpected response packet from %s during initial IP ID zombie testing", ip6_ntoa(&ip6.ip6_src)); + } continue; } diff --git a/libnetutil/netutil.cc b/libnetutil/netutil.cc index edb123f60..545863621 100644 --- a/libnetutil/netutil.cc +++ b/libnetutil/netutil.cc @@ -558,9 +558,9 @@ unsigned short in_cksum(const 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); +const u8 *ipv4_get_data(const struct ip *ip, const u8 *p, unsigned int *len); +const u8 *ipv6_get_data(const struct ip6_hdr *ip6, const u8 *p, unsigned int *len, u8 *nxt); +const u8 *ipv6_get_data_any(const struct ip6_hdr *ip6, const u8 *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 @@ -604,15 +604,15 @@ 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, const void *packet, +static const u8 *ipv6_get_data_primitive(const struct ip6_hdr *ip6, const u8 *packet, unsigned int *len, u8 *nxt, bool upperlayer_only) { - const unsigned char *p, *end; + const u8 *p, *end; if (*len < sizeof(*ip6)) return NULL; - p = (unsigned char *) packet; + p = packet; end = p + *len; *nxt = ip6->ip6_nxt; @@ -628,15 +628,19 @@ static const void *ipv6_get_data_primitive(const struct ip6_hdr *ip6, const void if (upperlayer_only && !ipv6_is_upperlayer(*nxt)) return NULL; - return (char *) p; + return p; } -static const void *ip_get_data_primitive(const void *packet, unsigned int *len, +static const u8 *ip_get_data_primitive(const u8 *packet, unsigned int *len, struct abstract_ip_hdr *hdr, bool upperlayer_only) { - struct ip ip; + if (*len < 20) + return NULL; - memcpy(&ip, packet, sizeof(ip)); - if (*len >= 20 && ip.ip_v == 4) { + u8 ip_v = packet[0] >> 4; + + if (ip_v == 4) { + struct ip ip; + memcpy(&ip, packet, sizeof(ip)); struct sockaddr_in *sin; hdr->version = 4; @@ -655,7 +659,7 @@ static const void *ip_get_data_primitive(const void *packet, unsigned int *len, 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) { + } else if (*len >= 40 && ip_v == 6) { struct ip6_hdr ip6; memcpy(&ip6, packet, sizeof(ip6)); struct sockaddr_in6 *sin6; @@ -684,7 +688,7 @@ static const void *ip_get_data_primitive(const void *packet, unsigned int *len, Returns the beginning of the payload, updates *len to be the length of the payload, and fills in hdr if successful. Otherwise returns NULL and *hdr is undefined. */ -const void *ip_get_data(const void *packet, unsigned int *len, +const u8 *ip_get_data(const u8 *packet, unsigned int *len, struct abstract_ip_hdr *hdr) { return ip_get_data_primitive(packet, len, hdr, true); } @@ -692,13 +696,13 @@ const void *ip_get_data(const void *packet, unsigned int *len, /* As ip_get_data, except that it doesn't insist that the payload be a known upper-layer protocol. This can matter in IPv6 where the last element of a nh chain may be a protocol we don't know about. */ -const void *ip_get_data_any(const void *packet, unsigned int *len, +const u8 *ip_get_data_any(const u8 *packet, unsigned int *len, struct abstract_ip_hdr *hdr) { return ip_get_data_primitive(packet, len, hdr, false); } /* Get the upper-layer protocol from an IPv4 packet. */ -const void *ipv4_get_data(const struct ip *ip, const void *p, unsigned int *len) +const u8 *ipv4_get_data(const struct ip *ip, const u8 *p, unsigned int *len) { unsigned int header_len; @@ -711,10 +715,10 @@ const void *ipv4_get_data(const struct ip *ip, const void *p, unsigned int *len) return NULL; *len -= header_len; - return (const u8 *)p + header_len; + return p + header_len; } -const void *ipv4_get_data(const void *p, unsigned int *len) +const u8 *ipv4_get_data(const u8 *p, unsigned int *len) { struct ip ip; memcpy(&ip, p, sizeof(ip)); @@ -724,12 +728,12 @@ const void *ipv4_get_data(const void *p, 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, const void *p, unsigned int *len, u8 *nxt) +const u8 *ipv6_get_data(const struct ip6_hdr *ip6, const u8 *p, unsigned int *len, u8 *nxt) { return ipv6_get_data_primitive(ip6, p, len, nxt, true); } -const void *ipv6_get_data(const void *p, unsigned int *len, u8 *nxt) +const u8 *ipv6_get_data(const u8 *p, unsigned int *len, u8 *nxt) { struct ip6_hdr ip6; memcpy(&ip6, p, sizeof(ip6)); @@ -739,19 +743,19 @@ const void *ipv6_get_data(const void *p, unsigned int *len, u8 *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, const void *p, unsigned int *len, u8 *nxt) +const u8 *ipv6_get_data_any(const struct ip6_hdr *ip6, const u8 *p, unsigned int *len, u8 *nxt) { return ipv6_get_data_primitive(ip6, p, len, nxt, false); } -const void *ipv6_get_data_any(const void *p, unsigned int *len, u8 *nxt) +const u8 *ipv6_get_data_any(const u8 *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) +const u8 *icmp_get_data(const u8 *icmp, unsigned int *len) { unsigned int header_len; struct icmp_hdr hdr; @@ -765,10 +769,10 @@ const void *icmp_get_data(const void *icmp, unsigned int *len) return NULL; *len -= header_len; - return (char *) icmp + header_len; + return icmp + header_len; } -const void *icmpv6_get_data(const void *icmpv6, unsigned int *len) +const u8 *icmpv6_get_data(const u8 *icmpv6, unsigned int *len) { unsigned int header_len; struct icmpv6_hdr hdr; @@ -782,7 +786,7 @@ const void *icmpv6_get_data(const void *icmpv6, unsigned int *len) return NULL; *len -= header_len; - return (char *) icmpv6 + header_len; + return icmpv6 + header_len; } diff --git a/libnetutil/netutil.h b/libnetutil/netutil.h index 4944fe30f..187400145 100644 --- a/libnetutil/netutil.h +++ b/libnetutil/netutil.h @@ -179,19 +179,19 @@ int ip_is_reserved(const struct sockaddr_storage *addr); int mac_cache_get(const struct sockaddr_storage *ss, u8 *mac); int mac_cache_set(const struct sockaddr_storage *ss, u8 *mac); -const void *ip_get_data(const void *packet, unsigned int *len, +const u8 *ip_get_data(const u8 *packet, unsigned int *len, struct abstract_ip_hdr *hdr); -const void *ip_get_data_any(const void *packet, unsigned int *len, +const u8 *ip_get_data_any(const u8 *packet, unsigned int *len, struct abstract_ip_hdr *hdr); /* Get the upper-layer protocol from an IPv4 packet. */ -const void *ipv4_get_data(const void *ip, unsigned int *len); +const u8 *ipv4_get_data(const u8 *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 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); +const u8 *ipv6_get_data(const u8 *ip6, unsigned int *len, u8 *nxt); +const u8 *ipv6_get_data_any(const u8 *ip6, unsigned int *len, u8 *nxt); +const u8 *icmp_get_data(const u8 *icmp, unsigned int *len); +const u8 *icmpv6_get_data(const u8 *icmpv6, unsigned int *len); /* Standard BSD internet checksum routine. */ unsigned short in_cksum(const u16 *ptr, int nbytes); diff --git a/nse_dnet.cc b/nse_dnet.cc index f9017cc33..4fafe2c6f 100644 --- a/nse_dnet.cc +++ b/nse_dnet.cc @@ -284,7 +284,7 @@ static int ip_send (lua_State *L) nseU_opttarget(L, 3, &addr, &targetname); payloadlen = packetlen; - if (ip_get_data_any(packet, &payloadlen, &hdr) == NULL) + if (ip_get_data_any((const u8 *)packet, &payloadlen, &hdr) == NULL) return luaL_error(L, "can't parse ip packet"); if (addr == NULL) { diff --git a/scan_engine_raw.cc b/scan_engine_raw.cc index 83aa008d3..f05391191 100644 --- a/scan_engine_raw.cc +++ b/scan_engine_raw.cc @@ -163,14 +163,14 @@ void UltraProbe::setIP(const u8 *ippacket, u32 len, const probespec *pspec) { type = UP_IP; if (ip->ip_v == 4) { - data = ipv4_get_data(ip, &len); + data = ipv4_get_data(ippacket, &len); assert(data != NULL); assert(len + ip->ip_hl * 4 == (u32) ntohs(ip->ip_len)); probes.IP.ipid = ntohs(ip->ip_id); hdr = ip->ip_p; } else if (ip->ip_v == 6) { const struct ip6_hdr *ip6 = (const struct ip6_hdr *) ippacket; - data = ipv6_get_data_any(ip6, &len, &hdr); + data = ipv6_get_data_any(ippacket, &len, &hdr); assert(data != NULL); assert(len == (u32) ntohs(ip6->ip6_plen)); probes.IP.ipid = ntohl(ip6->ip6_flow & IP6_FLOWLABEL_MASK); @@ -402,7 +402,7 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) { unsigned int listsz; reason_t current_reason = ER_NORESPONSE; - const void *data = NULL; + const u8 *data = NULL; unsigned int datalen; struct abstract_ip_hdr hdr; @@ -512,7 +512,7 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) { continue; encaps_len = datalen - 8; - encaps_data = ip_get_data((char *) data + 8, &encaps_len, &encaps_hdr); + encaps_data = ip_get_data(data + 8, &encaps_len, &encaps_hdr); if (encaps_data == NULL || /* UDP hdr, or TCP hdr up to seq #, or SCTP hdr up to vtag */ ((USI->tcp_scan || USI->udp_scan || USI->sctp_scan) && encaps_len < 8) @@ -1614,19 +1614,19 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) { reason_t current_reason = ER_NORESPONSE; struct sockaddr_storage reason_sip = { AF_UNSPEC }; - const void *data = NULL; + const u8 *data = NULL; unsigned int datalen; struct abstract_ip_hdr hdr; gettimeofday(&USI->now, NULL); do { - const struct ip *ip_tmp; + const u8 *ip_tmp; 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, &linkhdr, true); + ip_tmp = readip_pcap(USI->pd, &bytes, to_usec, &rcvdtime, &linkhdr, true); gettimeofday(&USI->now, NULL); if (!ip_tmp && TIMEVAL_BEFORE(*stime, USI->now)) { timedout = true; @@ -1746,7 +1746,7 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) { struct sctp_hdr sctp; memcpy(&sctp, data, sizeof(sctp)); struct dnet_sctp_chunkhdr chunk; - memcpy(&chunk, (u8 *)data + 12, sizeof(chunk)); + memcpy(&chunk, data + 12, sizeof(chunk)); u16 sport = ntohs(sctp.sh_sport); u16 dport = ntohs(sctp.sh_dport); @@ -1810,7 +1810,7 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) { continue; encaps_len = datalen - 8; - encaps_data = ip_get_data((char *) data + 8, &encaps_len, &encaps_hdr); + encaps_data = ip_get_data(data + 8, &encaps_len, &encaps_hdr); if (encaps_data == NULL || /* UDP hdr, or TCP hdr up to seq #, or SCTP hdr up to vtag */ ((USI->tcp_scan || USI->udp_scan || USI->sctp_scan) && encaps_len < 8) @@ -1909,7 +1909,7 @@ 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((const u8*)data, datalen); + nmap_hexdump(data, datalen); break; } current_reason = icmp_to_reason(hdr.proto, icmp.icmp_type, icmp.icmp_code); @@ -1938,7 +1938,7 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) { continue; encaps_len = datalen - 8; - encaps_data = ip_get_data_any((char *) data + 8, &encaps_len, &encaps_hdr); + encaps_data = ip_get_data_any(data + 8, &encaps_len, &encaps_hdr); if (encaps_data == NULL || /* UDP hdr, or TCP hdr up to seq #, or SCTP hdr up to vtag */ ((USI->tcp_scan || USI->udp_scan || USI->sctp_scan) && encaps_len < 8) diff --git a/tcpip.cc b/tcpip.cc index d602917f3..b68a09869 100644 --- a/tcpip.cc +++ b/tcpip.cc @@ -1059,8 +1059,10 @@ u8 *build_icmpv6_raw(const struct in6_addr *source, } /* At this point icmplen <= sizeof(*icmpv6) + sizeof(*msg). */ - memcpy(packet + icmplen, data, datalen); - icmplen += datalen; + if (data && datalen) { + memcpy(packet + icmplen, data, datalen); + icmplen += datalen; + } icmpv6->icmpv6_cksum = 0; icmpv6->icmpv6_cksum = ipv6_pseudoheader_cksum(source, victim, diff --git a/traceroute.cc b/traceroute.cc index c7bfa7a1e..3903ede23 100644 --- a/traceroute.cc +++ b/traceroute.cc @@ -1072,9 +1072,9 @@ struct Reply { _Type _Name; \ memcpy(&_Name, (u8 *)_Ptr + _Offset, MIN(_Len - _Offset, sizeof(_Type))); -static bool parse_encapsulated_reply(const void *ip, unsigned len, Reply *reply) { +static bool parse_encapsulated_reply(const u8 *ip, unsigned len, Reply *reply) { struct abstract_ip_hdr hdr; - const void *data; + const u8 *data; data = ip_get_data(ip, &len, &hdr); if (data == NULL) @@ -1118,9 +1118,9 @@ static bool parse_encapsulated_reply(const void *ip, unsigned len, Reply *reply) return true; } -static bool decode_reply(const void *ip, unsigned int len, Reply *reply) { +static bool decode_reply(const u8 *ip, unsigned int len, Reply *reply) { struct abstract_ip_hdr hdr; - const void *data; + const u8 *data; data = ip_get_data(ip, &len, &hdr); if (data == NULL) @@ -1137,7 +1137,7 @@ static bool decode_reply(const void *ip, unsigned int len, Reply *reply) { && icmp.icmp_code == ICMP_TIMEXCEED_INTRANS) || icmp.icmp_type == ICMP_UNREACH) { /* Get the encapsulated IP packet. */ - const void *encaps = icmp_get_data(data, &len); + const u8 *encaps = icmp_get_data(data, &len); if (encaps == NULL) return false; return parse_encapsulated_reply(encaps, len, reply); @@ -1164,7 +1164,7 @@ static bool decode_reply(const void *ip, unsigned int len, Reply *reply) { && icmpv6.icmpv6_code == ICMPV6_TIMEXCEED_INTRANS) || icmpv6.icmpv6_type == ICMPV6_UNREACH) { /* Get the encapsulated IP packet. */ - const void *encaps = icmpv6_get_data(data, &len); + const u8 *encaps = icmpv6_get_data(data, &len); if (encaps == NULL) return false; return parse_encapsulated_reply(encaps, len, reply); @@ -1200,7 +1200,7 @@ static bool decode_reply(const void *ip, unsigned int len, Reply *reply) { } static bool read_reply(Reply *reply, pcap_t *pd, long timeout) { - const void *ip; + const u8 *ip; unsigned int iplen; struct link_header linkhdr;