void send_icmp_timestamp(void) { char *packet; struct myicmphdr *icmp; struct icmp_tstamp_data *tstamp_data; packet = malloc(ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); if (packet == NULL) { perror("[send_icmp] malloc"); return; } memset(packet, 0, ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); icmp = (struct myicmphdr*) packet; tstamp_data = (struct icmp_tstamp_data*) (packet + ICMPHDR_SIZE); /* fill icmp hdr */ icmp->type = opt_icmptype; /* echo replay or echo request */ icmp->code = 0; icmp->checksum = 0; icmp->un.echo.id = getpid() & 0xffff; icmp->un.echo.sequence = _icmp_seq; tstamp_data->orig = htonl(get_midnight_ut_ms()); tstamp_data->recv = tstamp_data->tran = 0; /* icmp checksum */ if (icmp_cksum == -1) icmp->checksum = cksum((u_short*)packet, ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); else icmp->checksum = icmp_cksum; /* adds this pkt in delaytable */ if (opt_icmptype == ICMP_TIMESTAMP) delaytable_add(_icmp_seq, 0, time(NULL), get_usec(), S_SENT); /* send packet */ send_ip_handler(packet, ICMPHDR_SIZE + sizeof(struct icmp_tstamp_data)); free (packet); _icmp_seq++; }
/* -------------------------------- input ---------------------------------- */ static void receiver(struct portinfo *pi, int childpid) { struct myiphdr ip; char packet[IP_MAX_SIZE+linkhdr_size]; while(1) { int len, iplen; len = read_packet(packet, IP_MAX_SIZE+linkhdr_size); if (len == -1) { perror("read_packet"); continue; } /* minimal sanity checks */ if (len < linkhdr_size) continue; iplen = len - linkhdr_size; if (iplen < sizeof(struct myiphdr)) continue; /* copy the ip header in an access-safe place */ memcpy(&ip, packet+linkhdr_size, sizeof(ip)); /* check if the dest IP matches */ if (memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr))) continue; /* check if the source IP matches */ if (ip.protocol != IPPROTO_ICMP && memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr))) continue; if (ip.protocol == IPPROTO_TCP) { struct mytcphdr tcp; int iphdrlen = ip.ihl << 2; char flags[16]; time_t rttms; int sport; /* more sanity checks */ if ((iplen - iphdrlen) < sizeof(tcp)) continue; /* time to copy the TCP header in a safe place */ memcpy(&tcp, packet+linkhdr_size+iphdrlen, sizeof(tcp)); /* check if the TCP dest port matches */ #if 0 printf("SRC: %d DST: %d\n", ntohs(tcp.th_sport), ntohs(tcp.th_dport)); #endif if (ntohs(tcp.th_dport) != initsport) continue; sport = htons(tcp.th_sport); if (pi[sport].active == 0) continue; /* Note that we don't care about a wrote RTT * result due to resend on the same port. */ rttms = get_midnight_ut_ms() - pi[sport].sentms; avrgcount++; avrgms = (avrgms*(avrgcount-1)/avrgcount)+(rttms/avrgcount); /* The avrg RTT is shared using shared memory, * no locking... */ pi[MAXPORT+1].active = (int) avrgms; tcp_strflags(flags, tcp.th_flags); #if 0 printf("%5d: %s %3d %5d %5d %10ld (%2d)\n", sport, flags, ip.ttl, ip.id, ntohs(tcp.th_win), (long) rttms, opt_scan_probes-(pi[sport].retry)); #endif if ((tcp.th_flags & TH_SYN) || opt_verbose) { printf("%5d %-11.11s: %s %3d %5d %5d %5d\n", sport, port_to_name(sport), flags, ip.ttl, ip.id, ntohs(tcp.th_win), iplen); fflush(stdout); } pi[sport].active = 0; } else if (ip.protocol == IPPROTO_ICMP) { struct myicmphdr icmp; struct myiphdr subip; struct mytcphdr subtcp; int iphdrlen = ip.ihl << 2; unsigned char *p; int port; struct in_addr gwaddr; /* more sanity checks, we are only interested * in ICMP quoting the original packet. */ if ((iplen - iphdrlen) < sizeof(icmp)+sizeof(subip)+sizeof(subtcp)) continue; /* time to copy headers in a safe place */ p = (unsigned char *) packet+linkhdr_size+iphdrlen; //memcpy(&icmp, p, sizeof(subtcp)); //FIXME memcpy will always overflow destination buffer memmove(&icmp, p, sizeof(&icmp)); p += sizeof(icmp); memcpy(&subip, p, sizeof(ip)); p += sizeof(ip); memcpy(&subtcp, p, sizeof(subtcp)); /* Check if the ICMP quoted packet matches */ /* check if the source IP matches */ if (memcmp(&subip.saddr, &local.sin_addr, sizeof(subip.saddr))) continue; /* check if the destination IP matches */ if (memcmp(&subip.daddr, &remote.sin_addr, sizeof(subip.daddr))) continue; /* check if the quoted TCP packet port matches */ if (ntohs(subtcp.th_sport) != initsport) continue; port = htons(subtcp.th_dport); if (pi[port].active == 0) continue; pi[port].active = 0; memcpy(&gwaddr.s_addr, &ip.saddr, 4); printf("%5d: %3d %5d %5d (ICMP %3d %3d from %s)\n", port, ip.ttl, iplen, ntohs(ip.id), icmp.type, icmp.code, inet_ntoa(gwaddr)); } } }
/* -------------------------------- output ---------------------------------- */ static void sender(struct portinfo *pi) { int i, retry = 0; time_t start_time; start_time = get_midnight_ut_ms(); while(1) { int active = 0; int recvd = 0; retry ++; for (i = 0; i < MAXPORT; i++) { if (pi[i].active && pi[i].retry) { active++; pi[i].retry--; sequence = -1; dst_port = i; pi[i].sentms = get_midnight_ut_ms(); send_tcp(); if (opt_waitinusec) { if (usec_delay.it_interval.tv_usec) usleep(usec_delay.it_interval.tv_usec); } else { sleep(sending_wait); } } } avrgms = (float) pi[MAXPORT+1].active; if (retry >= 3) { if (opt_debug) printf("AVRGMS %f\n", avrgms); if (avrgms) usleep((int) (avrgms*1000)); else sleep(1); } for (i = 0; i < MAXPORT; i++) { if (!pi[i].active && pi[i].retry) recvd++; } /* More to scan? */ if (!active) { if (!recvd) sleep(1); fprintf(stderr, "All replies received. Done.\n"); printf("Not responding ports: "); for (i = 0; i < MAXPORT; i++) { if (pi[i].active && !pi[i].retry) printf("(%d %.11s) ", i, port_to_name(i)); } printf("\n"); exit(0); } /* Are we sending too fast? */ if ((!recvd && opt_waitinusec && usec_delay.it_interval.tv_usec == 0 && (get_midnight_ut_ms() - start_time) > 500) || (opt_scan_probes-retry) <= 2) { if (opt_debug) printf("SLOWING DONW\n"); usec_delay.it_interval.tv_usec *= 10; usec_delay.it_interval.tv_usec ++; } } }